(() => {
// add filters for all各种过滤器 - 优化版 V1.0
// 原作者版本: https://ld246.com/article/1736828257787
// chuchen接力版：增加按钮循环控制，css优化，支持拼音模糊搜索:首字母或全拼
// V0.2:支持混合逻辑语法:'空格 '分割关键词（AND逻辑），'竖线|'分割关键词（OR逻辑），'英文感叹号!'开头的关键词（NOT逻辑）,暂不支持转义
// V0.3:支持关键词高亮，支持Achuan大佬的最新的脚注面板https://ld246.com/article/1752516343833
// V0.4:支持按钮隐藏，在任意reset按钮连续右键3次恢复
// V0.5:支持移动端面板过滤器，MOBILE_ENABLED开关
// V0.6: 性能优化、模块化架构重构、添加LRU缓存机制管理优化、支持单个字全拼高亮、支持多音字识别和搜索、预加载拼音库
// V0.7: 优化文档树过滤体验，紧凑布局，扁平化样式
// V0.8：针对文档树过滤器进行超性能优化，预构建DOM映射，批量拼音转换，动态批次大小，智能调度策略
// V0.9：集成展开文档树功能，支持一键展开、折叠按钮递归深度控制、笔记本右键菜单展开、移动端长按展开
// V1.0：DOM查询缓存，批量事件委托 ,CSS选择器合并


// ================= 配置管理 =================
const CONFIG = {
    // 基础配置

    // 功能开关
    SHOW_BUTTON_DEFAULT: true, //过滤器按钮默认显示
    MOBILE_ENABLED: true,  // 移动端过滤器总开关，默认开启
    FULL_PINYIN_HIGHLIGHT: true,  // 是否启用全拼高亮，默认开启（可能影响性能）
    
    // 🆕 展开文档树功能开关
    EXPAND_TREE_ENABLED: true,  // 是否启用展开文档树功能，默认开启
    UNFOLD_ALL_SWITCH: true,    // 是否启用一键展开所有子节点功能
    
    // 🆕 日志系统配置
    LOG_PREFIX: '[Chuchen_各种过滤器_优化版]',
    LOG_LEVEL: 'info',    // 日志级别: debug | success | info | warn | error
    LOG_STYLES: {
        debug: 'color: #666;',
        info: 'color: #2196F3;',
        success: 'color: #4CAF50; font-weight: bold;',
        warn: 'color: #FF9800;',
        error: 'color: #f44336; font-weight: bold;'
    },
    
    // 拼音库源
    PINYIN_SOURCES: [
        '/plugins/myFonts/pinyin-pro.min.js',//建议把拼音库提前下载至本地，加载更快
        'https://cdn.bootcdn.net/ajax/libs/pinyin-pro/3.26.0/index.min.js',
        'https://unpkg.com/pinyin-pro@3.18.2/dist/index.js',
        'https://cdn.jsdelivr.net/npm/pinyin-pro@3.18.2/dist/index.js',
    ],
    
    // 🆕 存储配置
    STORAGE: {
        APP_ID: 'custom-snippet',                   // 统一的存储应用ID
        
        // 过滤器相关存储
        FILTER_BUTTON: 'myPlugin_showFilterButton',  // 过滤器按钮显示状态
        
        // 展开文档树相关存储
        TREE_EXPAND: {
            MAX_RECURSION_DEPTH: 'max_recursion_depth'  // 递归深度配置键名
        }
    },
        // 性能配置
        DEBOUNCE_DELAY: 250,
        CACHE_SIZE: 1000,  // LRU缓存大小，约可缓存1000个不同的文本片段
                          // 每个缓存项包含：{ initials: '字符串', full: '字符串' }
                          // 内存占用估算：1000项 × 平均50字节 ≈ 50KB
                          // 建议范围：500-2000，太小会频繁重新计算，太大会占用更多内存
        TIMEOUT: 5000,
        
        // 🆕 展开文档树性能配置
        MAX_RETRY_COUNT: 50,        // 最大重试次数
        RETRY_INTERVAL: 200,        // 重试间隔(毫秒)
        NODE_WAIT_TIME: 300,        // 统一的节点等待时间（毫秒）
        
        // 🆕 展开文档树功能配置
        MAX_RECURSION_DEPTH: 2,     // 最大递归深度默认值（每次点击最多递归2次，实际展开3层节点）
        SHOW_DEPTH_INFO: false,     // 是否显示深度信息（简化日志）
        ADD_TOP_BAR_BUTTON: true,   // 是否添加顶栏按钮
        
        // 🆕 展开所有笔记本配置
        EXPAND_ALL_NOTEBOOKS: {
            PARALLEL_EXPANSION: true,  // 是否并行展开（false=逐个展开，true=并行展开）
        },
        
        // 🆕 展开重试配置
        EXPANSION_RETRY: {
            MAX_RETRIES: 3,           // 最大重试次数
            INCREMENTAL_FACTOR: 0.5,  // 递增等待时间倍数
            MAX_TOTAL_WAIT: 5000      // 最大总等待时间(毫秒)
        },
        
        // 🆕 文件树刷新配置
        REFRESH_FILETREE: {
            ENABLED: true,            // 是否启用文件树刷新功能
            AFTER_EXPAND_ALL: true,   // 展开所有笔记本完成后是否刷新文件树
            FORCE_REFRESH: false,     // 是否强制刷新，忽略缓存
        }
};

// 过滤器配置
const FILTER_CONFIGS = [
    { id: 'tree_filter_container', placeholder: "文档树过滤器", selector: '.fn__flex-1.fn__flex-column.file-tree.sy__file', position: 'BEFORE_BEGIN' },
    { id: 'outline_filter_container', placeholder: "大纲过滤器", selector: '.fn__flex-1.fn__flex-column.file-tree.sy__outline', position: 'BEFORE_BEGIN' },
    { id: 'bmsp_filter_container', placeholder: "书签+过滤器", selector: '.fn__flex-1.b3-list.b3-list--background.custom-bookmark-body', position: 'BEFORE_END' },
    { id: 'tags_filter_container', placeholder: "标签过滤器", selector: '.fn__flex-1.fn__flex-column.file-tree.sy__tag', position: 'APPEND' },
    { id: 'bms_filter_container', placeholder: "书签过滤器", selector: '.fn__flex-1.fn__flex-column.file-tree.sy__bookmark', position: 'APPEND' },
    { id: 'backlink_filter_container', placeholder: "反链过滤器", selector: '.fn__flex-1.fn__flex-column.file-tree.sy__backlink', position: 'BEFORE_BEGIN' },
    { id: 'footnote_filter_container', placeholder: "脚注过滤器", selector: '.footnote-dock__content', position: 'INSERT_BEFORE' }

    // { id: 'flashcard_filter_container', placeholder: "闪卡过滤器", selector: '[data-key="dialog-viewcards"] .fn__flex-column', position: 'APPEND' }
];

const MOBILE_FILTER_CONFIGS = [
    { id: 'mobile_tree_filter_container', placeholder: "文档树过滤器", selector: '#sidebar [data-type="sidebar-file"] .fn__flex-1', position: 'BEFORE_BEGIN', tabType: 'sidebar-file-tab' },
    { id: 'mobile_outline_filter_container', placeholder: "大纲过滤器", selector: '#sidebar [data-type="sidebar-outline"] .fn__flex-1', position: 'BEFORE_BEGIN', tabType: 'sidebar-outline-tab' },
    { id: 'mobile_bookmark_filter_container', placeholder: "书签过滤器", selector: '#sidebar [data-type="sidebar-bookmark"] .fn__flex-1', position: 'BEFORE_BEGIN', tabType: 'sidebar-bookmark-tab' },
    { id: 'mobile_tag_filter_container', placeholder: "标签过滤器", selector: '#sidebar [data-type="sidebar-tag"] .fn__flex-1', position: 'BEFORE_BEGIN', tabType: 'sidebar-tag-tab' },
    { id: 'mobile_backlink_filter_container', placeholder: "反链过滤器", selector: '#sidebar [data-type="sidebar-backlink"] .fn__flex-1', position: 'BEFORE_BEGIN', tabType: 'sidebar-backlink-tab' },
    { id: 'mobile_inbox_filter_container', placeholder: "收集箱过滤器", selector: '#sidebar [data-type="sidebar-inbox"] .fn__flex-1', position: 'BEFORE_BEGIN', tabType: 'sidebar-inbox-tab' }
];

// ================= 🆕 日志管理器 =================
class Logger {
    constructor() {
        this.isDebug = CONFIG.LOG_LEVEL === 'debug';
        this.isSuccess = CONFIG.LOG_LEVEL === 'success';
        this.isInfo = CONFIG.LOG_LEVEL === 'info';
    }

    debug(...args) {
        if (this.isDebug) {
           console.log(`%c[DEBUG]%c${CONFIG.LOG_PREFIX}`, CONFIG.LOG_STYLES.debug, '', ...args);
        }
    }

    info(...args) {
        if (this.isDebug || this.isInfo) {
           console.log(`%c[INFO]%c${CONFIG.LOG_PREFIX}`, CONFIG.LOG_STYLES.info, '', ...args);
        }
    }

    success(...args) {
        if (this.isDebug || this.isSuccess) {
           console.log(`%c[SUCCESS]%c${CONFIG.LOG_PREFIX}`, CONFIG.LOG_STYLES.success, '', ...args);
        }
    }

    warn(...args) {
       console.warn(`%c[WARN]%c${CONFIG.LOG_PREFIX}`, CONFIG.LOG_STYLES.warn, '', ...args);
    }

    error(...args) {
       console.error(`%c[ERROR]%c${CONFIG.LOG_PREFIX}`, CONFIG.LOG_STYLES.error, '', ...args);
    }
}

// 创建全局日志实例
const logger = new Logger();

// ================= 工具类 =================
class Utils {
    // 防抖函数
    static debounce(fn, delay) {
        let timer = null;
        return function(...args) {
            clearTimeout(timer);
            timer = setTimeout(() => fn.apply(this, args), delay);
        };
    }

    // 节流函数
    static throttle(fn, delay) {
        let last = 0;
        return function(...args) {
            const now = Date.now();
            if (now - last >= delay) {
                last = now;
                fn.apply(this, args);
            }
        };
    }

    // 等待元素出现
    static whenElementExist(selector, node = document, timeout = CONFIG.TIMEOUT) {
        return new Promise((resolve, reject) => {
            const start = Date.now();
            const check = () => {
                try {
                    const el = typeof selector === 'function' ? selector() : node.querySelector(selector);
                    if (el) {
                        resolve(el);
                    } else if (Date.now() - start >= timeout) {
                        reject(new Error(`等待元素超时: ${selector}`));
                    } else {
                        requestAnimationFrame(check);
                    }
                } catch (err) {
                    reject(err);
                }
            };
            check();
        });
    }

    // 批量等待元素
    static whenAllElementsExist(selector) {
        return new Promise(resolve => {
            const check = () => {
                const elements = document.querySelectorAll(selector);
                if (elements.length > 0) {
                    resolve(Array.from(elements));
                } else {
                    requestAnimationFrame(check);
                }
            };
            check();
        });
    }

    // 判断移动端
    static isMobile() {
        return !!document.getElementById("sidebar");
    }

    // 安全获取元素
    static safeQuerySelector(selector, parent = document) {
        try {
            return parent.querySelector(selector);
        } catch (e) {
           logger.debug('选择器错误:', selector, e);
            return null;
        }
    }

    // 批量安全查询
    static safeQuerySelectorAll(selector, parent = document) {
        try {
            return Array.from(parent.querySelectorAll(selector));
        } catch (e) {
           logger.debug('选择器错误:', selector, e);
            return [];
        }
    }

    // 🆕 延时函数 - 用于等待展开动画完成
    static sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    // 🆕 获取元素的真实目标 - 处理SVG图标嵌套的情况
    static getRealTarget(element) {
        if (!element) return null;

        let target = element;
        const tagName = target.tagName?.toLowerCase();
            
        // 处理SVG元素嵌套
        if (tagName === 'use') {
            target = element.parentElement?.parentElement || element;
        } else if (tagName === 'svg') {
            target = element.parentElement || element;
        }

        return target;
    }

    // 🆕 判断用户点击的是否是折叠按钮
    static isArrowButton(element) {
        if (!element) return false;

        const target = Utils.getRealTarget(element);
        if (!target) return false;

        return target.tagName?.toLowerCase() === 'span' &&
            Utils.hasClass(target, 'b3-list-item__toggle');
    }

    // 🆕 获取折叠按钮对应的父节点
    static getParentLi(arrowSpan) {
        if (!arrowSpan) return null;

        const toggle = Utils.getRealTarget(arrowSpan);
        if (!toggle || !Utils.hasClass(toggle, 'b3-list-item__toggle')) {
            return null;
        }

        return toggle.parentElement;
    }

    // 🆕 查找子节点列表 - 优化版本
    static findChildList(parentLi) {
        if (!parentLi) return null;

        // 思源的规律：子节点列表总是跟在父节点后面
        let nextElement = parentLi.nextElementSibling;
        let depth = 0;
        const maxDepth = 3; // 减少最大深度检查

        while (nextElement && depth < maxDepth) {
            if (nextElement.tagName?.toLowerCase() === 'ul') {
                // 检查这个ul是否包含子节点
                const hasChildren = nextElement.querySelector('li[data-path]');
                if (hasChildren) {
                    return nextElement;
                }
            }

            nextElement = nextElement.nextElementSibling;
            depth++;
        }

        return null;
    }

    // 🆕 判断元素是否包含指定的CSS类名
    static hasClass(element, className) {
        return element?.classList?.contains(className) || false;
    }

    // 🆕 判断元素是否已展开 - 通过SVG的类名判断
    static isExpanded(element) {
        if (!element) return false;

        const toggle = Utils.getRealTarget(element);
        if (!toggle) return false;

        const svg = toggle.querySelector('svg');
        if (!svg) return false;

        return Utils.hasClass(svg, 'b3-list-item__arrow--open');
    }

    // 🆕 判断元素是否有子节点 - 优化版本
    static hasChildren(element) {
        if (!element) return false;

        const toggle = Utils.getRealTarget(element);
        if (!toggle || !Utils.hasClass(toggle, 'b3-list-item__toggle')) {
            return false;
        }

        // 关键：通过折叠按钮是否有fn__hidden类来判断是否有子节点
        return !Utils.hasClass(toggle, 'fn__hidden');
    }
}

// ================= LRU缓存类 =================
class LRUCache {
    constructor(maxSize = CONFIG.CACHE_SIZE) {
        this.maxSize = maxSize;
        this.cache = new Map();
    }

    get(key) {
        if (this.cache.has(key)) {
            const value = this.cache.get(key);
            this.cache.delete(key);
            this.cache.set(key, value);
            return value;
        }
        return null;
    }

    set(key, value) {
        if (this.cache.has(key)) {
            this.cache.delete(key);
        } else if (this.cache.size >= this.maxSize) {
            const firstKey = this.cache.keys().next().value;
            this.cache.delete(firstKey);
        }
        this.cache.set(key, value);
    }

    clear() {
        this.cache.clear();
    }

    get size() {
        return this.cache.size;
    }
}

// ================= 拼音管理器 =================
class PinyinManager {
    constructor() {
        this.cache = new LRUCache();
        this.pinyinLib = null;
        this.loadPromise = null;
    }

    async load() {
        if (this.pinyinLib) return this.pinyinLib;
        if (this.loadPromise) return this.loadPromise;

        this.loadPromise = new Promise((resolve) => {
            if (window.pinyinPro) {
                this.pinyinLib = window.pinyinPro;
                return resolve(this.pinyinLib);
            }

            let retryCount = 0;
            const tryNextSource = () => {
                if (retryCount >= CONFIG.PINYIN_SOURCES.length) {
                   logger.debug('拼音库加载失败');
                    return resolve(null);
                }

                const script = document.createElement('script');
                script.src = CONFIG.PINYIN_SOURCES[retryCount];
                script.onload = () => {
                    this.pinyinLib = window.pinyinPro;
                    resolve(this.pinyinLib);
                };
                script.onerror = () => {
                    retryCount++;
                    tryNextSource();
                };
                document.head.appendChild(script);
            };
            tryNextSource();
        });

        return this.loadPromise;
    }

    getPinyin(text) {
        const cached = this.cache.get(text);
        if (cached) return cached;

        if (!this.pinyinLib) return { initials: '', full: '' };

        try {
            const initials = this.pinyinLib.pinyin(text, { 
                pattern: 'first', 
                type: 'array', 
                toneType: 'none', 
                multiple: true 
            }).join('').toLowerCase();
            
            const full = this.pinyinLib.pinyin(text, { 
                pattern: 'pinyin', 
                type: 'array', 
                toneType: 'none', 
                multiple: true 
            }).join('').toLowerCase();
            
            const result = { initials, full };
            this.cache.set(text, result);
            return result;
        } catch (e) {
           logger.debug('拼音转换失败:', e);
            return { initials: '', full: '' };
        }
    }

    clearCache() {
        this.cache.clear();
    }
}

// ================= 存储管理器 =================
class StorageManager {
    static async setItem(key, value, appId = CONFIG.STORAGE.APP_ID) {
        try {
            const token = localStorage.getItem('authToken') || '';
            const response = await fetch('/api/storage/setLocalStorageVal', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Token ${token}`
                },
                body: JSON.stringify({ key, val: value, app: appId })
            });
            return response.json();
        } catch (e) {
           logger.debug('存储设置失败:', e);
            return { code: -1 };
        }
    }

    static async getItem(key, appId = CONFIG.STORAGE.APP_ID) {
        try {
            const token = localStorage.getItem('authToken') || '';
            const response = await fetch('/api/storage/getLocalStorage', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Token ${token}`
                },
                body: JSON.stringify({ app: appId })
            });
            const result = await response.json();
            
            if (result.code === 0 && result.data && typeof result.data === 'object') {
                const val = result.data[key];
                if (val === undefined) return null;
                if (val === false || val === 'false') return false;
                if (val === true || val === 'true') return true;
                return val;
            }
            return null;
        } catch (e) {
           logger.debug('存储获取失败:', e);
            return null;
        }
    }
}

// ================= 样式管理器 =================
class StyleManager {
    static addStyle(css) {
        const styleId = 'filter-highlight-style';
        let style = document.getElementById(styleId);
        if (!style) {
            style = document.createElement('style');
            style.id = styleId;
            document.head.appendChild(style);
        }
        style.textContent = css;
    }

    static initStyles() {
        const css = `
            /* ===== 基础样式 ===== */
            .filter_highlight {
                background-color: var(--b3-card-success-background) !important;
                color: var(--b3-card-info-color) !important;
                border-radius: 2px;
                padding: 1px 2px;
                box-shadow: 0 0 2px rgba(0,0,0,0.2) !important;
                opacity: 0.9 !important;
                font-weight: 600 !important;
            }
            
            /* ===== 移动端适配 ===== */
            #sidebar .filter_highlight {
                background-color: var(--b3-card-success-background) !important;
                color: var(--b3-card-success-color) !important;
                border-radius: 2px;
                padding: 1px 2px;
                box-shadow: 0 0 2px rgba(0,0,0,0.2) !important;
                opacity: 0.9 !important;
                font-weight: 600 !important;
            }
            
            #sidebar input[id*="filter_input"] {
                font-size: 14px;
                padding: 6px 8px;
                border-radius: 4px;
                margin: 4px 0;
            }
            
            #sidebar button.reset,
            #sidebar button.close {
                padding: 6px 10px;
                font-size: 12px;
                border-radius: 4px;
                min-width: 28px;
            }
            
            /* ===== 过滤器容器样式 ===== */
            .filter-container {
                display: flex;
                align-items: center;
                gap: 3px;
            }
            
            .filter-input {
                flex: 1;
                min-width: 0;
                border: 1px dashed var(--b3-theme-on-surface);
                background-color: var(--b3-theme-surface);
                color: var(--b3-theme-on-background);
                padding: 4px 8px;
                border-radius: 4px;
            }
            
            .filter-button {
                color: var(--color-text-3);
                font-weight: 900;
                cursor: pointer;
                background-color: var(--b3-theme-surface-light);
                border: 1px dotted var(--b3-theme-on-surface);
                padding: 4px 6px;
                border-radius: 3px;
                min-width: 28px;
                font-size: 12px;
            }
            
            /* ===== 🆕 性能优化：合并的紧凑布局样式 ===== */
            /* 隐藏过滤掉的项目 */
            .file-tree .b3-list-item.filtered-out,
            .fn__flex-column[data-type="sidebar-file"] .b3-list-item.filtered-out,
            .file-tree[data-filtering="true"] .b3-list-item.filtered-out {
                display: none !important;
                height: 0 !important;
                margin: 0 !important;
                padding: 0 !important;
                overflow: hidden !important;
            }
            
            /* 扁平化样式 - 支持filtering类和data-filtering属性 */
            .file-tree.filtering .b3-list-item:not(.filtered-out),
            .fn__flex-column[data-type="sidebar-file"].filtering .b3-list-item:not(.filtered-out),
            .file-tree[data-filtering="true"] .b3-list-item:not(.filtered-out),
            .fn__flex-column[data-type="sidebar-file"][data-filtering="true"] .b3-list-item:not(.filtered-out) {
                --file-toggle-width: 0px !important;
                margin-left: 0 !important;
                padding-left: 0 !important;
                position: relative !important;
                left: 0 !important;
            }
            
            /* 折叠按钮样式重置 */
            .file-tree.filtering .b3-list-item:not(.filtered-out) .b3-list-item__toggle,
            .fn__flex-column[data-type="sidebar-file"].filtering .b3-list-item:not(.filtered-out) .b3-list-item__toggle,
            .file-tree[data-filtering="true"] .b3-list-item:not(.filtered-out) .b3-list-item__toggle,
            .fn__flex-column[data-type="sidebar-file"][data-filtering="true"] .b3-list-item:not(.filtered-out) .b3-list-item__toggle {
                padding-left: 0px !important;
                margin-left: 0 !important;
                transform: translateX(0) !important;
            }
            
            /* 🆕 性能优化：合并的子元素样式重置 */
            .file-tree.filtering .b3-list-item:not(.filtered-out) .b3-list-item__icon,
            .file-tree.filtering .b3-list-item:not(.filtered-out) .b3-list-item__text,
            .file-tree.filtering .b3-list-item:not(.filtered-out) .b3-list-item__toggle,
            .fn__flex-column[data-type="sidebar-file"].filtering .b3-list-item:not(.filtered-out) .b3-list-item__icon,
            .fn__flex-column[data-type="sidebar-file"].filtering .b3-list-item:not(.filtered-out) .b3-list-item__text,
            .fn__flex-column[data-type="sidebar-file"].filtering .b3-list-item:not(.filtered-out) .b3-list-item__toggle,
            .file-tree[data-filtering="true"] .b3-list-item:not(.filtered-out) .b3-list-item__icon,
            .file-tree[data-filtering="true"] .b3-list-item:not(.filtered-out) .b3-list-item__text,
            .file-tree[data-filtering="true"] .b3-list-item:not(.filtered-out) .b3-list-item__toggle,
            .fn__flex-column[data-type="sidebar-file"][data-filtering="true"] .b3-list-item:not(.filtered-out) .b3-list-item__icon,
            .fn__flex-column[data-type="sidebar-file"][data-filtering="true"] .b3-list-item:not(.filtered-out) .b3-list-item__text,
            .fn__flex-column[data-type="sidebar-file"][data-filtering="true"] .b3-list-item:not(.filtered-out) .b3-list-item__toggle {
                margin-left: 0 !important;
                padding-left: 0 !important;
            }
            
            /* 🆕 性能优化：合并的过滤器保护样式 */
            .file-tree.filtering .filter-container,
            .fn__flex-column[data-type="sidebar-file"].filtering .filter-container,
            .file-tree.filtering .filter-input,
            .fn__flex-column[data-type="sidebar-file"].filtering .filter-input,
            .file-tree.filtering .filter-button,
            .fn__flex-column[data-type="sidebar-file"].filtering .filter-button,
            .file-tree[data-filtering="true"] .filter-container,
            .fn__flex-column[data-type="sidebar-file"][data-filtering="true"] .filter-container,
            .file-tree[data-filtering="true"] .filter-input,
            .fn__flex-column[data-type="sidebar-file"][data-filtering="true"] .filter-input,
            .file-tree[data-filtering="true"] .filter-button,
            .fn__flex-column[data-type="sidebar-file"][data-filtering="true"] .filter-button {
                margin-left: initial !important;
                padding-left: initial !important;
                position: static !important;
                left: auto !important;
                transform: none !important;
            }
            
            /* 🆕 性能优化：合并的强制覆盖样式 */
            .file-tree.filtering .b3-list-item:not(.filtered-out)[style*="--file-toggle-width"],
            .fn__flex-column[data-type="sidebar-file"].filtering .b3-list-item:not(.filtered-out)[style*="--file-toggle-width"],
            .file-tree[data-filtering="true"] .b3-list-item:not(.filtered-out)[style*="--file-toggle-width"],
            .fn__flex-column[data-type="sidebar-file"][data-filtering="true"] .b3-list-item:not(.filtered-out)[style*="--file-toggle-width"] {
                --file-toggle-width: 0px !important;
            }
            
            .file-tree.filtering .b3-list-item:not(.filtered-out) .b3-list-item__toggle[style*="padding-left"],
            .fn__flex-column[data-type="sidebar-file"].filtering .b3-list-item:not(.filtered-out) .b3-list-item__toggle[style*="padding-left"],
            .file-tree[data-filtering="true"] .b3-list-item:not(.filtered-out) .b3-list-item__toggle[style*="padding-left"],
            .fn__flex-column[data-type="sidebar-file"][data-filtering="true"] .b3-list-item:not(.filtered-out) .b3-list-item__toggle[style*="padding-left"] {
                padding-left: 0px !important;
                margin-left: 0px !important;
            }
            
            /* ===== 🆕 展开文档树样式 ===== */
            
            /* 1. 紧凑的工具栏图标样式 */
            .fn__flex-1.b3-list--mobile [data-type="sidebar-file"] .toolbar.toolbar--border.toolbar--dark .toolbar__icon {
                padding: 8px !important;
                margin: 3px 4px !important;
            }
            
            /* 2. 展开按钮样式 */
            .fn__flex-1.b3-list--mobile [data-type="sidebar-file"] .toolbar.toolbar--border.toolbar--dark [data-type="expand-all-notebooks"] {
                height: 18px !important;
                width: 18px !important;
                padding: 8px !important;
                flex-shrink: 0 !important;
                margin: 3px 4px !important;
                color: var(--b3-theme-on-surface) !important;
                border-radius: var(--b3-border-radius) !important;
                display: flex !important;
                align-items: center !important;
                justify-content: center !important;
                font-size: 18px !important;
                cursor: pointer !important;
                transition: background-color 0.2s !important;
            }
            
            /* 3. 递归深度选择器样式 */
            .recursion-depth-selector {
                animation: fadeInScale 0.2s ease-out;
            }
            
            .recursion-depth-selector > div {
                vertical-align: middle;
                margin: 0;
                padding: 0;
                line-height: 1.2;
                display: flex;
                align-items: center;
            }
            
            @keyframes fadeInScale {
                from {
                    opacity: 0;
                    transform: scale(0.9);
                }
                to {
                    opacity: 1;
                    transform: scale(1);
                }
            }
            
            /* 移动端触摸优化 */
            @media (max-width: 768px) {
                .recursion-depth-selector {
                    min-width: 160px !important;
                    max-width: 180px !important;
                    font-size: 16px !important;
                }
                
                .recursion-depth-selector > div {
                    padding: 4px 8px !important;
                    margin: 1px 0 !important;
                }
            }
            
            /* 4. 移动端长按提示样式 */
            .mobile-longpress-tip {
                position: fixed;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
                background: var(--b3-theme-background);
                color: var(--b3-theme-on-surface);
                padding: 12px 20px;
                border-radius: 8px;
                box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
                border: 1px solid var(--b3-theme-border);
                z-index: 9999;
                font-size: 16px;
                font-weight: 500;
                animation: fadeInScale 0.3s ease-out;
            }
            
            /* 5. 移动端提示动画 */
            @keyframes fadeInScale {
                from {
                    opacity: 0;
                    transform: translate(-50%, -50%) scale(0.8);
                }
                to {
                    opacity: 1;
                    transform: translate(-50%, -50%) scale(1);
                }
            }
        `;
        this.addStyle(css);
    }
}

// ================= 过滤器核心类 =================
class FilterCore {
    constructor() {
        this.pinyinManager = new PinyinManager();
        this.activeFilters = new Set();
        this.observers = [];
    }

    // 解析过滤条件
    parseFilterText(filterText) {
        const orGroups = filterText.toLowerCase().split('|').map(group =>
            group.split(' ').filter(k => k.trim()).map(term => ({
                value: term.replace(/^!/, ''),
                isNot: term.startsWith('!')
            }))
        );
        return orGroups;
    }

    // 检查文本匹配
    checkTextMatch(text, pinyinData, orGroups) {
        const lowerText = text.toLowerCase();
        const { initials, full } = pinyinData;

        return orGroups.some(group =>
            group.every(({ value, isNot }) => {
                const hasMatch = [
                    lowerText.includes(value),
                    initials.includes(value),
                    full.includes(value)
                ].some(Boolean);
                return isNot ? !hasMatch : hasMatch;
            })
        );
    }

    // 高亮文本
    highlightText(originalText, highlightTerms) {
        if (!highlightTerms || highlightTerms.length === 0) {
            return document.createTextNode(originalText);
        }

        const fragment = document.createDocumentFragment();
        let lastIndex = 0;

        // 收集所有匹配位置
        const matchPositions = new Set();
        const lowerOriginal = originalText.toLowerCase();

        highlightTerms.forEach(term => {
            if (!term || term.length === 0) return;

            const lowerTerm = term.toLowerCase();
            let pos = -1;

            // 文本匹配
            while ((pos = lowerOriginal.indexOf(lowerTerm, pos + 1)) !== -1) {
                for (let i = 0; i < term.length; i++) {
                    matchPositions.add(pos + i);
                }
            }
        });

        if (matchPositions.size === 0) {
            return document.createTextNode(originalText);
        }

        // 构建高亮片段
        const sortedPositions = Array.from(matchPositions).sort((a, b) => a - b);
        const regexParts = [];
        let currentStart = sortedPositions[0];
        let currentEnd = currentStart + 1;

        for (let i = 1; i < sortedPositions.length; i++) {
            if (sortedPositions[i] === currentEnd) {
                currentEnd++;
            } else {
                regexParts.push(originalText.slice(currentStart, currentEnd));
                currentStart = sortedPositions[i];
                currentEnd = currentStart + 1;
            }
        }

        if (sortedPositions.length > 0) {
            regexParts.push(originalText.slice(currentStart, currentEnd));
        }

        const regexPattern = regexParts
            .map(str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
            .join('|');

        if (regexPattern) {
            const regex = new RegExp(`(${regexPattern})`, 'gi');
            let match;
            while ((match = regex.exec(originalText)) !== null) {
                if (match.index > lastIndex) {
                    fragment.appendChild(document.createTextNode(
                        originalText.slice(lastIndex, match.index)
                    ));
                }
                const highlight = document.createElement('span');
                highlight.className = 'filter_highlight';
                highlight.textContent = match[0];
                fragment.appendChild(highlight);
                lastIndex = regex.lastIndex;
            }
        }

        if (lastIndex < originalText.length) {
            fragment.appendChild(document.createTextNode(
                originalText.slice(lastIndex)
            ));
        }

        return fragment;
    }

    // 构建高亮片段 - 支持拼音匹配
    buildHighlightFragment(originalText, pinyin, highlightTerms) {
        // 如果高亮词为空，直接返回原文本
        if (!highlightTerms || highlightTerms.length === 0) {
            const textNode = document.createTextNode(originalText);
            return textNode;
        }
        
        const fragment = document.createDocumentFragment();
        let lastIndex = 0;
        
        // 优化：只处理需要高亮的词，避免处理所有字符
        const matchPositions = new Set();
        const lowerOriginal = originalText.toLowerCase();
        
        highlightTerms.forEach(term => {
            if (!term || term.length === 0) return;
            
            const lowerTerm = term.toLowerCase();
            let pos = -1;
            
            // 查找文本匹配
            while ((pos = lowerOriginal.indexOf(lowerTerm, pos + 1)) !== -1) {
                for (let i = 0; i < term.length; i++) {
                    matchPositions.add(pos + i);
                }
            }
            
            // 查找拼音匹配（只对中文和拼音词进行）
            if (/^[a-z]{1,}$/.test(lowerTerm)) {
                // 使用整个文本的拼音转换来获得正确的多音字识别
                const textPinyin = pinyin.pinyin(originalText, { 
                    pattern: 'pinyin', 
                    type: 'array', 
                    toneType: 'none',
                    multiple: true
                });
                const textInitials = pinyin.pinyin(originalText, { 
                    pattern: 'first', 
                    type: 'array', 
                    toneType: 'none',
                    multiple: true
                });
                
                // 构建字符到拼音的映射
                const pinyinMap = [];
                let charIndex = 0;
                
                for (let i = 0; i < textPinyin.length; i++) {
                    const pinyinGroup = textPinyin[i];
                    const initialsGroup = textInitials[i];
                    
                    // 每个拼音组对应一个字符
                    const char = originalText[charIndex];
                    
                    // 确保拼音组是数组格式
                    const allPinyin = Array.isArray(pinyinGroup) ? pinyinGroup.map(p => p.toLowerCase()) : [pinyinGroup.toLowerCase()];
                    const allInitials = Array.isArray(initialsGroup) ? initialsGroup.map(p => p.toLowerCase()) : [initialsGroup.toLowerCase()];
                    
                    pinyinMap.push({
                        char: char,
                        initials: allInitials.join(''),  // 所有首字母组合
                        full: allPinyin.join(''),       // 所有全拼组合
                        allPinyin: allPinyin,           // 所有全拼数组
                        allInitials: allInitials,       // 所有首字母数组
                        index: charIndex
                    });
                    
                    charIndex++;
                }
                
                // 单字符拼音首字母匹配（支持多音字）
                pinyinMap.forEach((p, index) => {
                    if (p.allInitials.includes(lowerTerm)) {
                        matchPositions.add(index);
                    }
                });
                
                // 单字符拼音全拼匹配（仅在启用时，支持多音字）
                if (CONFIG.FULL_PINYIN_HIGHLIGHT) {
                    pinyinMap.forEach((p, index) => {
                        if (p.allPinyin.includes(lowerTerm)) {
                            matchPositions.add(index);
                        }
                    });
                }
                
                // 多字符拼音首字母匹配
                if (lowerTerm.length >= 2) {
                    const initialsSequence = pinyinMap.map(p => p.initials).join('');
                    let pos = -1;
                    while ((pos = initialsSequence.indexOf(lowerTerm, pos + 1)) !== -1) {
                        for (let i = 0; i < lowerTerm.length; i++) {
                            const charIndex = pos + i;
                            if (charIndex < pinyinMap.length) {
                                matchPositions.add(pinyinMap[charIndex].index);
                            }
                        }
                    }
                }
                
                // 多字符拼音全拼匹配（仅在启用时）
                if (CONFIG.FULL_PINYIN_HIGHLIGHT && lowerTerm.length >= 2) {
                    const fullSequence = pinyinMap.map(p => p.full).join('');
                    let pos = -1;
                    while ((pos = fullSequence.indexOf(lowerTerm, pos + 1)) !== -1) {
                        // 找到匹配的起始位置，需要计算对应的字符位置
                        let charIndex = 0;
                        let currentPos = 0;
                        for (let i = 0; i < pinyinMap.length; i++) {
                            const pinyinLength = pinyinMap[i].full.length;
                            if (currentPos <= pos && pos < currentPos + pinyinLength) {
                                charIndex = i;
                                break;
                            }
                            currentPos += pinyinLength;
                        }
                        // 高亮匹配的字符
                        matchPositions.add(charIndex);
                    }
                }
            }
        });
        
        // 如果没有匹配，直接返回原文本
        if (matchPositions.size === 0) {
            const textNode = document.createTextNode(originalText);
            return textNode;
        }
        
        // 构建高亮片段
        const sortedPositions = Array.from(matchPositions).sort((a, b) => a - b);
        const regexParts = [];
        let currentStart = sortedPositions[0];
        let currentEnd = currentStart + 1;
        
        for (let i = 1; i < sortedPositions.length; i++) {
            if (sortedPositions[i] === currentEnd) {
                currentEnd++;
            } else {
                regexParts.push(originalText.slice(currentStart, currentEnd));
                currentStart = sortedPositions[i];
                currentEnd = currentStart + 1;
            }
        }
        
        if (sortedPositions.length > 0) {
            regexParts.push(originalText.slice(currentStart, currentEnd));
        }
        
        const regexPattern = regexParts
            .map(str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
            .join('|');
        
        if (regexPattern) {
            const regex = new RegExp(`(${regexPattern})`, 'gi');
            let match;
            while ((match = regex.exec(originalText)) !== null) {
                if (match.index > lastIndex) {
                    fragment.appendChild(document.createTextNode(
                        originalText.slice(lastIndex, match.index)
                    ));
                }
                const highlight = document.createElement('span');
                highlight.className = 'filter_highlight';
                highlight.textContent = match[0];
                fragment.appendChild(highlight);
                lastIndex = regex.lastIndex;
            }
        }
        
        if (lastIndex < originalText.length) {
            fragment.appendChild(document.createTextNode(
                originalText.slice(lastIndex)
            ));
        }
        
        return fragment;
    }

    // 处理过滤器输入
    async handleFilterInput(input, selector, id) {
        const filterText = input.value;
        
        const orGroups = this.parseFilterText(filterText);
        const highlightTerms = orGroups.flatMap(group =>
            group.filter(term => !term.isNot).map(term => term.value)
        );

        // 获取目标元素
        const elements = this.getTargetElements(selector, id);
        
        if (elements.length === 0) return;

        // 批量处理
        const updates = [];
        const pinyinLib = await this.pinyinManager.load();

        // 特殊处理脚注面板
        if (id === 'footnote_filter_container') {
            try {
                if (!pinyinLib?.pinyin) throw new Error('拼音库初始化失败');
                
                elements.forEach(item => {
                    const text = item.innerText;
                    const lowerText = text.toLowerCase();
                    const { initials: pinyinInitials, full: pinyinFull } = this.pinyinManager.getPinyin(text);
                    
                    const matchAnyGroup = orGroups.some(group =>
                        group.every(({ value, isNot }) => {
                            const hasMatch = [
                                lowerText.includes(value),
                                pinyinInitials.includes(value),
                                pinyinFull.includes(value)
                            ].some(Boolean);
                            return isNot ? !hasMatch : hasMatch;
                        })
                    );
                    
                    item.style.display = matchAnyGroup ? '' : 'none';
                    
                    // 只对原文命中做高亮
                    if (matchAnyGroup) {
                        const spans = item.querySelectorAll('div[contenteditable="true"]');
                        spans.forEach(span => {
                            const spanText = span.textContent;
                            if (!filterText) {
                                // 清空时还原原始HTML
                                if (span.dataset.originalHtml) {
                                    span.innerHTML = span.dataset.originalHtml;
                                    delete span.dataset.originalHtml;
                                }
                            } else if (span.childNodes.length === 1 && span.childNodes[0].nodeType === 3) {
                                // 高亮前缓存原始HTML
                                if (!span.dataset.originalHtml) {
                                    span.dataset.originalHtml = span.innerHTML;
                                }
                                let innerHTML = spanText;
                                highlightTerms.forEach(value => {
                                    if (value) {
                                        const reg = new RegExp(value, 'gi');
                                        innerHTML = innerHTML.replace(reg, match => `<span class="filter_highlight">${match}</span>`);
                                    }
                                });
                                span.innerHTML = innerHTML;
                            }
                        });
                    }
                });
            } catch (e) {
                // 降级为纯文本过滤+高亮
                elements.forEach(item => {
                    const text = item.innerText;
                    const lowerText = text.toLowerCase();
                    const matchAnyGroup = orGroups.some(group =>
                        group.every(({ value, isNot }) => {
                            const hasMatch = lowerText.includes(value);
                            return isNot ? !hasMatch : hasMatch;
                        })
                    );
                    
                    item.style.display = matchAnyGroup ? '' : 'none';
                    
                    if (matchAnyGroup) {
                        const spans = item.querySelectorAll('div[contenteditable="true"]');
                        spans.forEach(span => {
                            const spanText = span.textContent;
                            if (!filterText) {
                                if (span.dataset.originalHtml) {
                                    span.innerHTML = span.dataset.originalHtml;
                                    delete span.dataset.originalHtml;
                                }
                            } else if (span.childNodes.length === 1 && span.childNodes[0].nodeType === 3) {
                                if (!span.dataset.originalHtml) {
                                    span.dataset.originalHtml = span.innerHTML;
                                }
                                let innerHTML = spanText;
                                orGroups.flat().forEach(({ value }) => {
                                    if (value) {
                                        const reg = new RegExp(value, 'gi');
                                        innerHTML = innerHTML.replace(reg, match => `<span class="filter_highlight">${match}</span>`);
                                    }
                                });
                                span.innerHTML = innerHTML;
                            }
                        });
                    }
                });
            }
            return;
        }

        // 处理文档树等面板的紧凑布局
        if (id === 'tree_filter_container' || id === 'mobile_tree_filter_container') {
            this.handleTreeFilterWithCompactLayout(filterText, selector, id, elements, orGroups, highlightTerms, pinyinLib);
            return;
        }

        elements.forEach(element => {
            const originalText = element.dataset.originalText || element.textContent;
            if (!element.dataset.originalText) {
                element.dataset.originalText = originalText;
            }

            const pinyinData = pinyinLib ? this.pinyinManager.getPinyin(originalText) : { initials: '', full: '' };
            const matchAnyGroup = this.checkTextMatch(originalText, pinyinData, orGroups);

            updates.push({
                element,
                parent: element.parentElement,
                matchAnyGroup,
                originalText,
                highlightTerms,
                pinyinLib
            });
        });

        // 批量应用更新
        updates.forEach(({ element, parent, matchAnyGroup, originalText, highlightTerms, pinyinLib }) => {
            element.textContent = originalText;
            if (parent && parent.style) {
                parent.style.display = matchAnyGroup ? '' : 'none';
            }
            
            if (matchAnyGroup && highlightTerms.length > 0) {
                element.innerHTML = '';
                if (pinyinLib) {
                    element.appendChild(this.buildHighlightFragment(originalText, pinyinLib, highlightTerms));
                } else {
                    element.appendChild(this.highlightText(originalText, highlightTerms));
                }
            }
        });
    }

    // 处理文档树过滤的紧凑布局 - 超优化版：最小化DOM操作，最大化批量处理
    handleTreeFilterWithCompactLayout(filterText, selector, id, elements, orGroups, highlightTerms, pinyinLib) {
        // 获取文档树容器 - 使用配置化选择器
        const containerSelectors = {
            desktop: '.file-tree',
            mobile: '[data-type="sidebar-file"]'
        };
        
        const isMobile = Utils.isMobile();
        const containerSelector = containerSelectors[isMobile ? 'mobile' : 'desktop'];
        const fileTree = elements[0]?.closest(containerSelector);
        
        if (fileTree) {
            if (filterText) {
                // 🆕 修复：检查容器是否已经具有layout__tab--active类
                // 如果具有，则使用data属性标记过滤状态，避免添加filtering类
                if (fileTree.classList.contains('layout__tab--active')) {
                    fileTree.dataset.filtering = 'true';
                } else {
                    fileTree.classList.add('filtering');
                }
            } else {
                // 清理过滤状态
                if (fileTree.classList.contains('filtering')) {
                    fileTree.classList.remove('filtering');
                }
                if (fileTree.dataset.filtering === 'true') {
                    delete fileTree.dataset.filtering;
                }
            }
        }
        
        // 如果没有过滤条件，快速恢复所有样式和高亮
        if (!filterText) {
            if (fileTree) {
                this.restoreAllHiddenItems(fileTree);
            }
            // 清理所有高亮，恢复原始文本
            this.clearAllHighlights(elements);
            return;
        }
        
        // 🆕 性能优化：预构建DOM映射，缓存所有需要的DOM元素
        const domMap = this.buildOptimizedDOMMap(elements);
        
        // 超优化第二阶段：批量拼音转换（如果启用）
        let pinyinCache = null;
        if (pinyinLib && CONFIG.FULL_PINYIN_HIGHLIGHT) {
            pinyinCache = this.batchPinyinConversion(elements, pinyinLib);
        }
        
        // 超优化第三阶段：批量匹配计算
        const matchResults = this.batchMatchCalculation(elements, orGroups, pinyinCache);
        
        // 🆕 性能优化：连接DOM映射数据，避免重复查询
        matchResults.forEach((result, index) => {
            result.domMapData = domMap.domMap.get(result.element);
        });
        
        // 超优化第四阶段：批量DOM操作
        this.batchDOMOperations(matchResults, fileTree);
        
        // 超优化第五阶段：智能高亮处理
        if (highlightTerms.length > 0) {
            this.smartHighlightProcessing(matchResults, highlightTerms, pinyinLib);
        }
    }
    
    // 🆕 新增：优化的DOM映射构建，缓存所有需要的DOM元素
    buildOptimizedDOMMap(elements) {
        const domMap = new Map();
        const listItems = new Set();
        const toggles = new Set();
        const textElements = new Set();
        
        // 一次性收集所有需要的DOM元素
        elements.forEach(element => {
            const listItem = element.closest('.b3-list-item');
            if (listItem) {
                domMap.set(element, {
                    listItem: listItem,
                    toggle: listItem.querySelector('.b3-list-item__toggle'),
                    textElement: listItem.querySelector('.b3-list-item__text')
                });
                
                listItems.add(listItem);
                
                // 缓存toggle和text元素
                const toggle = listItem.querySelector('.b3-list-item__toggle');
                if (toggle) toggles.add(toggle);
                
                const textElement = listItem.querySelector('.b3-list-item__text');
                if (textElement) textElements.add(textElement);
            }
        });
        
        return { 
            domMap, 
            listItems: Array.from(listItems),
            toggles: Array.from(toggles),
            textElements: Array.from(textElements)
        };
    }
    
    // 批量拼音转换
    batchPinyinConversion(elements, pinyinLib) {
        const pinyinCache = new Map();
        
        // 收集所有需要转换的文本
        const textsToConvert = new Set();
        elements.forEach(element => {
            const text = element.dataset.originalText || element.textContent;
            if (!element.dataset.originalText) {
                element.dataset.originalText = text;
            }
            textsToConvert.add(text);
        });
        
        // 批量转换拼音
        textsToConvert.forEach(text => {
            pinyinCache.set(text, this.pinyinManager.getPinyin(text));
        });
        
        return pinyinCache;
    }
    
    // 批量匹配计算
    batchMatchCalculation(elements, orGroups, pinyinCache) {
        const results = [];
        
        elements.forEach(element => {
            const originalText = element.dataset.originalText || element.textContent;
            const pinyinData = pinyinCache ? pinyinCache.get(originalText) : { initials: '', full: '' };
            const matchAnyGroup = this.checkTextMatch(originalText, pinyinData, orGroups);
            
            results.push({
                element,
                listItem: null, // 稍后填充
                matchAnyGroup,
                originalText,
                pinyinData,
                // 🆕 性能优化：添加DOM映射数据引用
                domMapData: null
            });
        });
        
        return results;
    }
    
    // 批量DOM操作
    batchDOMOperations(matchResults, fileTree) {
        const matchedItems = [];
        const unmatchedItems = [];
        
        // 🆕 性能优化：使用缓存的DOM元素，避免重复查询
        matchResults.forEach(result => {
            const cachedData = result.domMapData;
            if (cachedData && cachedData.listItem) {
                result.listItem = cachedData.listItem;
                
                if (result.matchAnyGroup) {
                    cachedData.listItem.classList.remove('filtered-out');
                    matchedItems.push(cachedData.listItem);
                } else {
                    cachedData.listItem.classList.add('filtered-out');
                    unmatchedItems.push(cachedData.listItem);
                }
            }
        });
        
        // 批量应用扁平化样式
        if (matchedItems.length > 0) {
            // 直接操作收集到的元素，避免重复查询
            matchedItems.forEach(listItem => {
                listItem.classList.add('filtered-flat');
            });
        }
    }
    
    // 智能高亮处理
    smartHighlightProcessing(matchResults, highlightTerms, pinyinLib) {
        const toHighlight = matchResults.filter(r => r.matchAnyGroup);
        
        if (toHighlight.length === 0) return;
        
        // 根据数量选择处理策略
        if (toHighlight.length <= 20) {
            // 少量元素：同步处理
            this.syncHighlightProcessing(toHighlight, highlightTerms, pinyinLib);
        } else {
            // 大量元素：异步分批处理
            this.asyncHighlightProcessing(toHighlight, highlightTerms, pinyinLib);
        }
    }
    
    // 同步高亮处理
    syncHighlightProcessing(toHighlight, highlightTerms, pinyinLib) {
        toHighlight.forEach(({ element, originalText }) => {
            element.innerHTML = '';
            if (pinyinLib) {
                element.appendChild(this.buildHighlightFragment(originalText, pinyinLib, highlightTerms));
            } else {
                element.appendChild(this.highlightText(originalText, highlightTerms));
            }
        });
    }
    
    // 异步高亮处理
    asyncHighlightProcessing(toHighlight, highlightTerms, pinyinLib) {
        const batchSize = Math.max(5, Math.floor(toHighlight.length / 10)); // 动态批次大小
        let currentIndex = 0;
        
        const processBatch = () => {
            const endIndex = Math.min(currentIndex + batchSize, toHighlight.length);
            
            for (let i = currentIndex; i < endIndex; i++) {
                const { element, originalText } = toHighlight[i];
                element.innerHTML = '';
                if (pinyinLib) {
                    element.appendChild(this.buildHighlightFragment(originalText, pinyinLib, highlightTerms));
                } else {
                    element.appendChild(this.highlightText(originalText, highlightTerms));
                }
            }
            
            currentIndex = endIndex;
            
            if (currentIndex < toHighlight.length) {
                // 使用更智能的调度
                if (endIndex - currentIndex > batchSize * 2) {
                    // 还有大量工作，使用setTimeout避免阻塞
                    setTimeout(processBatch, 0);
                } else {
                    // 接近完成，使用requestAnimationFrame
                    requestAnimationFrame(processBatch);
                }
            }
        };
        
        processBatch();
    }
    
    // 批量处理高亮，避免阻塞UI
    batchProcessHighlights(toHighlight, highlightTerms) {
        const batchSize = 10; // 每批处理10个元素
        let currentIndex = 0;
        
        const processBatch = () => {
            const endIndex = Math.min(currentIndex + batchSize, toHighlight.length);
            
            for (let i = currentIndex; i < endIndex; i++) {
                const { element, originalText, pinyinLib } = toHighlight[i];
                element.innerHTML = '';
                if (pinyinLib) {
                    element.appendChild(this.buildHighlightFragment(originalText, pinyinLib, highlightTerms));
                } else {
                    element.appendChild(this.highlightText(originalText, highlightTerms));
                }
            }
            
            currentIndex = endIndex;
            
            if (currentIndex < toHighlight.length) {
                // 还有元素需要处理，继续下一批
                requestAnimationFrame(processBatch);
            }
        };
        
        // 开始处理第一批
        requestAnimationFrame(processBatch);
    }
    
    // 清理所有高亮，恢复原始文本
    clearAllHighlights(elements) {
        elements.forEach(element => {
            if (element.dataset.originalText) {
                element.textContent = element.dataset.originalText;
            }
        });
    }

    // 统一的样式恢复方法
    restoreAllHiddenItems(container) {
        const allHiddenItems = container.querySelectorAll('.b3-list-item.filtered-out');
        
        allHiddenItems.forEach(listItem => {
            this.restoreItem(listItem);
        });
        
        return allHiddenItems.length;
    }
    
    // 恢复单个项目的样式
    restoreItem(listItem) {
        // 移除过滤相关的类
        listItem.classList.remove('filtered-out', 'filtered-flat');
        
        // 恢复原始缩进样式
        listItem.style.removeProperty('--file-toggle-width');
        const toggle = listItem.querySelector('.b3-list-item__toggle');
        if (toggle) {
            toggle.style.removeProperty('padding-left');
            toggle.style.removeProperty('margin-left');
        }
        
        // 恢复原始文本
        const textElement = listItem.querySelector('.b3-list-item__text');
        if (textElement && textElement.dataset.originalText) {
            textElement.textContent = textElement.dataset.originalText;
        }
    }

    // 获取目标元素
    getTargetElements(selector, id) {
        const isMobile = Utils.isMobile();
        
        if (id === 'backlink_filter_container' || id === 'mobile_backlink_filter_container') {
            return [
                ...Utils.safeQuerySelectorAll(selector + ' .p[contenteditable="true"]'),
                ...Utils.safeQuerySelectorAll(selector + ' li span.b3-list-item__text.ariaLabel')
            ];
        } else if (id === 'footnote_filter_container') {
            return Utils.safeQuerySelectorAll('.footnote-item');
        } else {
            if (isMobile) {
                if (id === 'mobile_tree_filter_container') {
                    return Utils.safeQuerySelectorAll(selector + ' li span.b3-list-item__text');
                } else {
                    return Utils.safeQuerySelectorAll(selector + ' li span.b3-list-item__text.ariaLabel');
                }
            } else {
                return Utils.safeQuerySelectorAll(selector + ' li span.b3-list-item__text.ariaLabel');
            }
        }
    }

    // 重置过滤器显示
    resetFilterDisplay(selector) {
        const isMobile = Utils.isMobile();
        
        // 普通面板
        let spans;
        if (isMobile) {
            if (selector.includes('sidebar-file')) {
                spans = Utils.safeQuerySelectorAll(selector + ' li span.b3-list-item__text');
            } else {
                spans = Utils.safeQuerySelectorAll(selector + ' li span.b3-list-item__text.ariaLabel');
            }
        } else {
            spans = Utils.safeQuerySelectorAll(selector + ' li span.b3-list-item__text.ariaLabel');
        }

        // 🆕 优化：批量处理，减少DOM操作次数
        const updates = [];
        spans.forEach(span => {
            const listItem = span.parentElement;
            if (listItem && listItem.style) {
                updates.push({
                    element: listItem,
                    span: span
                });
            }
        });

        // 批量应用更新
        updates.forEach(({ element, span }) => {
            element.style.display = '';
            // 移除紧凑布局相关的类
            element.classList.remove('filtered-out', 'filtered-flat');
            
            // 恢复原始缩进样式
            element.style.removeProperty('--file-toggle-width');
            const toggle = element.querySelector('.b3-list-item__toggle');
            if (toggle) {
                toggle.style.removeProperty('padding-left');
                toggle.style.removeProperty('margin-left');
            }
            
            if (span.dataset.originalText) {
                span.textContent = span.dataset.originalText;
            } else {
                span.innerHTML = span.textContent;
            }
        });
        
        // 移除文档树的过滤状态类 - 使用配置化选择器
        const containerSelectors = {
            desktop: '.file-tree',
            mobile: '[data-type="sidebar-file"]'
        };
        
        const containerSelector = containerSelectors[isMobile ? 'mobile' : 'desktop'];
        const fileTree = Utils.safeQuerySelector(selector + containerSelector);
        if (fileTree) {
            // 🆕 优化：先检查是否有变化，避免不必要的操作
            const hasFilteringClass = fileTree.classList.contains('filtering');
            const hasFilteringData = fileTree.dataset.filtering === 'true';
            
            if (hasFilteringClass || hasFilteringData) {
                // 🆕 使用requestAnimationFrame延迟执行，避免在事件处理过程中触发观察器
                requestAnimationFrame(() => {
                    if (hasFilteringClass) {
                        fileTree.classList.remove('filtering');
                    }
                    if (hasFilteringData) {
                        delete fileTree.dataset.filtering;
                    }
                    
                    // 恢复所有可能被隐藏的项目
                    this.restoreAllHiddenItems(fileTree);
                });
            }
        }

        // 脚注面板
        const footnoteSpans = [
            ...Utils.safeQuerySelectorAll(selector + ' .protyle-wysiwyg[contenteditable="true"] div[contenteditable="true"]'),
            ...Utils.safeQuerySelectorAll(selector + ' .footnote-item span')
        ];

        footnoteSpans.forEach(span => {
            if (span.parentElement && span.parentElement.style) {
                span.parentElement.style.display = '';
            }
            if (span.childNodes.length === 1 && span.childNodes[0].nodeType === 3) {
                span.innerHTML = span.textContent;
            }
        });
    }

    // 清理资源
    cleanup() {
        this.activeFilters.clear();
        this.observers.forEach(observer => observer.disconnect());
        this.observers.length = 0;
        this.pinyinManager.clearCache();
    }

    // 清除拼音缓存（用于调试）
    clearPinyinCache() {
        this.pinyinManager.clearCache();
    }
}

// ================= 过滤器UI管理器 =================
class FilterUIManager {
    constructor(filterCore) {
        this.filterCore = filterCore;
        this.resetClickCount = 0;
        // 🆕 性能优化：添加事件委托
        this.initializeEventDelegation();
    }

    // 🆕 新增：事件委托初始化
    initializeEventDelegation() {
        // 使用事件委托处理所有过滤器的事件
        document.addEventListener('input', Utils.debounce(async (e) => {
            if (e.target.classList.contains('filter-input')) {
                const id = e.target.id.replace('filter_input', '');
                await this.filterCore.handleFilterInput(e.target, this.getSelectorById(id), id);
            }
        }, CONFIG.DEBOUNCE_DELAY));

        document.addEventListener('click', async (e) => {
            if (e.target.classList.contains('filter-button')) {
                const container = e.target.closest('.filter-container');
                if (!container) return;
                
                const id = container.id;
                const input = container.querySelector('.filter-input');
                
                if (e.target.classList.contains('reset')) {
                    input.value = '';
                    this.filterCore.resetFilterDisplay(this.getSelectorById(id));
                } else if (e.target.classList.contains('close')) {
                    input.value = '';
                    this.filterCore.resetFilterDisplay(this.getSelectorById(id));
                    container.remove();
                }
            }
        });

        // 右键恢复按钮功能
        document.addEventListener('contextmenu', async (e) => {
            if (e.target.classList.contains('filter-button') && e.target.classList.contains('reset')) {
                const showButton = await StorageManager.getItem(CONFIG.STORAGE.FILTER_BUTTON);
                if (showButton === false) {
                    e.preventDefault();
                    this.resetClickCount++;
                    if (this.resetClickCount >= 3) {
                        await StorageManager.setItem(CONFIG.STORAGE.FILTER_BUTTON, true);
                        location.reload();
                    }
                    setTimeout(() => { this.resetClickCount = 0; }, 1500);
                }
            }
        });
    }

    // 创建过滤器容器
    createFilterContainer(id, placeholder) {
        const container = document.createElement('div');
        container.id = id;
        container.className = 'filter-container';

        const input = document.createElement('input');
        input.id = 'filter_input' + id;
        input.type = 'text';
        input.placeholder = placeholder;
        input.className = 'filter-input b3-text-field fn__block';

        const resetButton = document.createElement('button');
        resetButton.textContent = '↺';
        resetButton.className = 'filter-button reset';
        resetButton.title = '重置过滤器';

        const closeButton = document.createElement('button');
        closeButton.textContent = '⨉';
        closeButton.className = 'filter-button close';
        closeButton.title = '关闭过滤器';

        // 🆕 性能优化：移除独立的事件监听器，改用事件委托
        // 事件委托将在FilterUIManager中统一处理

        container.appendChild(resetButton);
        container.appendChild(input);
        container.appendChild(closeButton);

        return container;
    }

    // 根据ID获取选择器
    getSelectorById(id) {
        const configs = Utils.isMobile() ? MOBILE_FILTER_CONFIGS : FILTER_CONFIGS;
        const config = configs.find(c => c.id === id);
        return config ? config.selector : '';
    }

    // 插入过滤器容器
    insertFilterContainer(container, selector, position) {
        const targetElement = Utils.safeQuerySelector(selector);
        if (!targetElement) return;

        const positionMap = {
            'BEFORE': () => targetElement.parentElement.insertBefore(container, targetElement),
            'BEFORE_BEGIN': () => targetElement.parentElement.insertAdjacentElement('beforeBegin', container),
            'APPEND': () => targetElement.appendChild(container),
            'BEFORE_END': () => targetElement.parentElement.insertAdjacentElement('beforeEnd', container),
            'PREPEND': () => targetElement.prepend(container),
            'AFTER_BEGIN': () => targetElement.parentElement.insertAdjacentElement('afterBegin', container),
            'INSERT_BEFORE': () => targetElement.insertAdjacentElement('beforeBegin', container)
        };

        const insertMethod = positionMap[position];
        if (insertMethod) {
            insertMethod();
        }
    }

    // 添加过滤器
    addFilter(config) {
        const { id, placeholder, selector, position } = config;
        
        // 移除已存在的过滤器
        const existingFilter = document.getElementById(id);
        if (existingFilter) {
            existingFilter.remove();
        }

        // 检查目标元素是否存在且可见
        const targetElement = Utils.safeQuerySelector(selector);
        if (!targetElement) {
            logger.debug(`❌ 目标元素未找到: ${selector}`);
            return;
        }

        const isMobile = Utils.isMobile();
        if (isMobile) {
            const panelType = selector.match(/data-type="([^"]+)"/)?.[1];
            if (panelType) {
                const panel = Utils.safeQuerySelector(`#sidebar [data-type="${panelType}"]`);
                if (panel && panel.classList.contains('fn__none')) {
                    return;
                }
            }
        } else {
            const hiddenPanel = Utils.safeQuerySelector(selector + '.fn__none');
            if (hiddenPanel) {
                return;
            }

            const parentPanel = targetElement.closest('[data-type^="sidebar-"]');
            if (parentPanel && parentPanel.classList.contains('fn__none')) {
                return;
            }
        }

        // 创建并插入过滤器
        const container = this.createFilterContainer(id, placeholder);
        this.insertFilterContainer(container, selector, position);
    }

    // 移除特定Tab的过滤器
    removeTabFilters(tabType) {
        const configs = MOBILE_FILTER_CONFIGS;
        const targetConfig = configs.find(config => config.tabType === tabType);
        
        if (targetConfig) {
            const filter = document.getElementById(targetConfig.id);
            if (filter) {
                filter.remove();
            }
        }
    }

    // 移除所有过滤器
    removeAllFilters() {
        const configs = Utils.isMobile() ? MOBILE_FILTER_CONFIGS : FILTER_CONFIGS;
        configs.forEach(config => {
            const filter = document.getElementById(config.id);
            if (filter) {
                filter.remove();
            }
        });
    }

    // 添加所有过滤器
    addAllFilters() {
        const configs = Utils.isMobile() ? MOBILE_FILTER_CONFIGS : FILTER_CONFIGS;
        const isMobile = Utils.isMobile();

        if (isMobile) {
            const activeTab = Utils.safeQuerySelector('#sidebar .toolbar__icon--active');
            if (activeTab) {
                const activeTabType = activeTab.getAttribute('data-type');
                
                if (activeTabType === 'sidebar-plugin-tab') {
                    this.removeAllFilters();
                    return;
                }

                const activeConfig = configs.find(config => config.tabType === activeTabType);
                if (activeConfig) {
                    try {
                        this.addFilter(activeConfig);
                    } catch (error) {
                       logger.debug('添加过滤器失败:', error);
                    }
                }
            }
        } else {
            configs.forEach((config) => {
                try {
                    this.addFilter(config);
                } catch (error) {
                   logger.debug('添加过滤器失败:', error);
                }
            });
        }
    }
}

// ================= 观察器管理器 =================
class ObserverManager {
    constructor(filterUIManager) {
        this.filterUIManager = filterUIManager;
        this.observers = [];
    }

    // 启动Tab观察器
    startTabObserver() {
        const isMobile = Utils.isMobile();
        
        if (isMobile) {
            this.startMobileTabObserver();
        } else {
            this.startDesktopTabObserver();
        }
    }

    // 桌面端Tab观察器
    startDesktopTabObserver() {
        Utils.whenAllElementsExist('.layout-tab-container.fn__flex-1').then((parentElements) => {
            parentElements.forEach((parentElement, index) => {
                const observer = new MutationObserver((mutationsList) => {
                    for (const mutation of mutationsList) {
                        if (mutation.type === 'childList') {
                            mutation.addedNodes.forEach(node => {
                                if (node.classList?.contains('layout__tab--active')) {
                                    this.filterUIManager.addAllFilters();
                                }
                            });
                        }
                        if (mutation.type === 'attributes' && mutation.target.classList?.contains('layout__tab--active')) {
                            const target = mutation.target;
                            const oldValue = mutation.oldValue || '无';
                            const newValue = target.className;
                            
                            // 🆕 修复：检查是否只是添加了filtering类，如果是则忽略
                            // 处理mutation.oldValue为undefined的情况
                            if (mutation.oldValue === undefined) {
                                // 如果oldValue是undefined，说明这是第一次检测到变化
                                // 检查新值是否包含filtering类，如果是则可能是过滤操作
                                if (newValue.includes('filtering') && newValue.includes('layout__tab--active')) {
                                    // 检查是否只是添加了filtering类（从已有的layout__tab--active变为layout__tab--active filtering）
                                    const hasLayoutTabActive = newValue.includes('layout__tab--active');
                                    const hasFiltering = newValue.includes('filtering');
                                    
                                    if (hasLayoutTabActive && hasFiltering) {
                                        return;
                                    }
                                }
                            } else {
                                // 如果有oldValue，使用原来的逻辑
                                const oldClasses = oldValue.split(' ').filter(c => c.trim());
                                const newClasses = newValue.split(' ').filter(c => c.trim());
                                
                                // 检查是否只是添加了filtering类，而没有其他重要变化
                                const addedClasses = newClasses.filter(c => !oldClasses.includes(c));
                                const removedClasses = oldClasses.filter(c => !newClasses.includes(c));
                                
                                // 如果只是添加了filtering类，说明是过滤操作，不是真正的Tab切换
                                if (addedClasses.length === 1 && addedClasses[0] === 'filtering' && removedClasses.length === 0) {
                                    return;
                                }
                            }
                            
                            // 如果添加了其他类（如layout__tab--active），说明是真正的Tab切换
                            if (newValue.includes('layout__tab--active')) {
                                this.filterUIManager.addAllFilters();
                            }
                        }
                    }
                });
                
                observer.observe(parentElement, {
                    childList: true,
                    subtree: true,
                    attributes: true,
                    attributeFilter: ['class']
                });
                
                this.observers.push(observer);
            });
        }).catch(() => {
            const documentObserver = new MutationObserver((mutationsList) => {
                for (const mutation of mutationsList) {
                    if (mutation.target.classList?.contains('layout__tab--active')) {
                        this.filterUIManager.addAllFilters();
                    }
                }
            });
            
            documentObserver.observe(document, {
                childList: true,
                subtree: true,
                attributes: true,
                attributeFilter: ['class']
            });
            
            this.observers.push(documentObserver);
        });
    }

    // 移动端Tab观察器
    startMobileTabObserver() {
        const sidebar = document.getElementById('sidebar');
        if (!sidebar) return;

        // 监听tab点击事件
        const tabClickHandler = Utils.throttle((event) => {
            const target = event.target.closest('[data-type*="sidebar-"][data-type*="-tab"]');
            if (target) {
                setTimeout(() => {
                    this.filterUIManager.addAllFilters();
                }, 100);
            }
        }, 200);

        sidebar.addEventListener('click', tabClickHandler);

        // 监听class变化
        const observer = new MutationObserver((mutationsList) => {
            for (const mutation of mutationsList) {
                if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
                    const target = mutation.target;
                    
                    // 当Tab变为active时，添加过滤器
                    if (target.classList.contains('toolbar__icon--active')) {
                        setTimeout(() => {
                            this.filterUIManager.addAllFilters();
                        }, 100);
                    } 
                    // 当Tab从active变为非active时，移除对应的过滤器
                    else if (target.classList.contains('toolbar__icon') && 
                             target.hasAttribute('data-type') && 
                             !target.classList.contains('toolbar__icon--active')) {
                        setTimeout(() => {
                            this.filterUIManager.removeTabFilters(target.getAttribute('data-type'));
                        }, 100);
                    }
                }
            }
        });

        observer.observe(sidebar, {
            attributes: true,
            attributeFilter: ['class'],
            subtree: true
        });

        this.observers.push(observer);
    }



    // 停止所有观察器
    stopAllObservers() {
        this.observers.forEach(observer => observer.disconnect());
        this.observers.length = 0;
    }
}

// ================= 按钮管理器 =================
class ButtonManager {
    constructor(filterUIManager) {
        this.filterUIManager = filterUIManager;
        this.isActive = false;
    }

    // 添加控制按钮
    async addButton(pin) {
        const showButton = await StorageManager.getItem(CONFIG.STORAGE.FILTER_BUTTON);
        if (showButton === false) return;

        const button = document.createElement('span');
        button.className = 'dock__item ariaLabel';
        button.textContent = '🕸️';
        button.setAttribute('aria-label', '关闭筛选过滤器\n右击可隐藏按钮');

        button.onclick = (event) => {
            event.preventDefault();
            event.stopPropagation();
            
            this.filterUIManager.removeAllFilters();
            
            if (this.isActive) {
                this.filterUIManager.addAllFilters();
            }
            
            this.isActive = !this.isActive;
            button.setAttribute('aria-label', 
                this.isActive ? '开启筛选过滤器\n右击可隐藏按钮' : '关闭筛选过滤器\n右击可隐藏按钮'
            );
            button.textContent = this.isActive ? '🕸︎' : '🕸️';
        };

        button.addEventListener('contextmenu', async (e) => {
            e.preventDefault();
            if (confirm('隐藏过滤器按钮？\n可通过reset按钮连续右键3次恢复')) {
                await StorageManager.setItem(CONFIG.STORAGE.FILTER_BUTTON, false);
                button.remove();
            }
        });

        pin.before(button);
    }
}

// ================= 主应用类 =================
class FilterApp {
    constructor() {
        this.filterCore = new FilterCore();
        this.filterUIManager = new FilterUIManager(this.filterCore);
        this.observerManager = new ObserverManager(this.filterUIManager);
        this.buttonManager = new ButtonManager(this.filterUIManager);
        
        // 🆕 添加展开文档树管理器
        if (CONFIG.EXPAND_TREE_ENABLED) {
            this.treeExpandManager = new TreeExpandManager();
        }
    }

    // 添加所有过滤器
    addAllFilters() {
        this.filterUIManager.addAllFilters();
    }

    // 移除所有过滤器
    removeAllFilters() {
        this.filterUIManager.removeAllFilters();
    }

    // 初始化应用
    async init() {
        try {
            // 初始化样式
            StyleManager.initStyles();

            const isMobile = Utils.isMobile();

            if (isMobile) {
                // 移动端初始化 - 检查开关
                if (CONFIG.MOBILE_ENABLED) {
                    await Utils.whenElementExist('#sidebar');
                    this.addAllFilters();
                    this.observerManager.startTabObserver();
                } else {
                    //logger.debug('移动端过滤器已禁用');
                    return;
                }
            } else {
                // 桌面端初始化
                const pin = await Utils.whenElementExist('#dockLeft .dock__items .dock__item--pin');
                await this.buttonManager.addButton(pin);
                this.addAllFilters();
                this.observerManager.startTabObserver();
            }

            // 🆕 新增：初始化展开文档树功能
            if (CONFIG.EXPAND_TREE_ENABLED && this.treeExpandManager) {
                await this.initTreeExpandFeatures();
            }

            // 注册清理函数
            this.registerCleanup();

            // 预加载拼音库以减少首次使用时的卡顿
            this.preloadPinyinLibrary();

        } catch (error) {
            logger.debug('过滤器初始化失败:', error);
        }
    }
    


    // 🆕 初始化展开文档树功能
    async initTreeExpandFeatures() {
        try {
            logger.debug('🚀 开始初始化展开文档树功能...');
            
            // 从本地存储加载递归深度配置
            const savedDepth = await StorageManager.getItem(CONFIG.STORAGE.TREE_EXPAND.MAX_RECURSION_DEPTH, CONFIG.STORAGE.APP_ID);
            if (savedDepth !== null) {
                CONFIG.MAX_RECURSION_DEPTH = savedDepth;
                logger.debug(`✅ 从本地存储加载递归深度配置: ${CONFIG.MAX_RECURSION_DEPTH}`);
            } else {
                logger.debug(`🔄 本地存储中未找到递归深度配置，使用默认值: ${CONFIG.MAX_RECURSION_DEPTH}`);
            }
            
            // 确保按钮标签显示正确的递归深度信息
            this.treeExpandManager.updateAllButtonLabels();
            
            // 添加顶栏按钮
            await this.addTreeExpandButtons();
            
            // 使用全局事件委托，统一处理桌面端和移动端的折叠按钮点击
            this.initializeGlobalEventDelegation();
            
            // 注入右键菜单
            setTimeout(() => {
                this.injectRightClickMenu();
            }, 1000); // 延迟1秒注入
            
            logger.debug('✅ 展开文档树功能初始化完成');
        } catch (error) {
            logger.debug('❌ 展开文档树功能初始化失败:', error);
        }
    }

    // 🆕 添加展开文档树按钮
    async addTreeExpandButtons() {
        try {
            const isMobile = Utils.isMobile();
            
            if (isMobile) {
                // 移动端：在工具栏中添加按钮
                logger.debug("🚀 开始处理移动端按钮添加...");
                await this.addMobileTreeExpandButton();
            } else {
                // 桌面端：在文档树顶栏中添加按钮
                logger.debug("🚀 开始处理桌面端按钮添加...");
                await this.addDesktopTreeExpandButton();
            }
        } catch (error) {
            logger.debug("❌ 添加展开文档树按钮失败:", error);
        }
    }

    // 🆕 桌面端顶栏按钮添加
    async addDesktopTreeExpandButton() {
        // 等待文档树顶栏出现
        const topBar = await Utils.whenElementExist('.sy__file .block__icons');
        if (!topBar) {
            logger.debug("❌ 未找到桌面端文档树顶栏");
            return;
        }
        
        // 等待"折叠"按钮出现
        const collapseButton = await Utils.whenElementExist('[data-type="collapse"]', topBar);
        if (!collapseButton) {
            logger.debug("❌ 未找到桌面端折叠按钮");
            return;
        }
        
        // 检查按钮是否已存在
        const existingButton = topBar.querySelector('[data-type="expand-all-notebooks"]');
        if (existingButton) {
            logger.debug("✅ 桌面端展开按钮已存在，跳过添加");
            return;
        }
        
        // 创建"展开所有笔记本"按钮 - 使用SVG图标
        const expandAllButton = document.createElement('span');
        expandAllButton.className = 'block__icon b3-tooltips b3-tooltips__sw';
        expandAllButton.setAttribute('data-type', 'expand-all-notebooks');
        
        // 动态设置aria-label，包含当前递归深度信息
        expandAllButton.setAttribute('aria-label', this.treeExpandManager.getCurrentDepthLabel());
        expandAllButton.innerHTML = '<svg><use xlink:href="#iconExpand"></use></svg>';
        
        // 创建间距分隔符
        const spaceSpan = document.createElement('span');
        spaceSpan.className = 'fn__space';
        
        // 添加点击事件
        expandAllButton.addEventListener('click', () => {
            this.treeExpandManager.handleExpandAllNotebooks();
        });
        
        // 添加桌面端右击事件
        expandAllButton.addEventListener('contextmenu', (e) => {
            e.preventDefault(); // 阻止默认右击菜单
            this.treeExpandManager.showRecursionDepthSelector(e, expandAllButton);
        });
        
        // 在折叠按钮前面插入按钮和间距
        topBar.insertBefore(spaceSpan, collapseButton);
        topBar.insertBefore(expandAllButton, spaceSpan);
        
        logger.debug("✅ 桌面端顶栏按钮'展开所有笔记本'添加成功，支持右击修改递归深度");
    }

    // 🆕 移动端顶栏按钮添加
    async addMobileTreeExpandButton() {
        logger.debug("🔍 开始添加移动端工具栏按钮...");
        
        try {
            // 检查当前激活的面板
            const activeTab = document.querySelector('#sidebar .toolbar__icon--active');
            if (!activeTab) {
                logger.debug("❌ 未找到激活的移动端面板");
                return;
            }
            
            const activeTabType = activeTab.getAttribute('data-type');
            logger.debug(`🔍 当前激活的移动端面板: ${activeTabType}`);
            
            // 只处理文档树面板
            if (activeTabType !== 'sidebar-file-tab') {
                logger.debug(`⚠️ 当前面板不是文档树 (${activeTabType})，跳过添加按钮`);
                return;
            }

            // 查找移动端工具栏
            const toolbar = document.querySelector('[data-type="sidebar-file"] .toolbar.toolbar--border.toolbar--dark');
            if (!toolbar) {
                logger.debug("❌ 未找到移动端工具栏");
                return;
            }
            
            logger.debug("✅ 找到移动端工具栏");
            
            // 检查是否已经存在我们的按钮
            const existingButton = toolbar.querySelector('[data-type="expand-all-notebooks"]');
            if (existingButton) {
                logger.debug("✅ 移动端按钮已存在，跳过添加");
                return;
            }
            
            // 创建"展开所有笔记本"按钮 - 使用emoji图标
            const expandAllButton = document.createElement('div');
            expandAllButton.className = 'toolbar__icon';
            expandAllButton.setAttribute('data-type', 'expand-all-notebooks');
            
            // 动态设置aria-label，包含当前递归深度信息
            expandAllButton.setAttribute('aria-label', this.treeExpandManager.getCurrentDepthLabel());
            expandAllButton.textContent = '📖';
            
            // 添加点击事件
            expandAllButton.addEventListener('click', () => {
                this.treeExpandManager.handleExpandAllNotebooks();
            });
            
            // 添加移动端长按事件
            let longPressTimer = null;
            let longPressDelay = 500; // 500ms长按延迟
            
            expandAllButton.addEventListener('touchstart', (e) => {
                longPressTimer = setTimeout(() => {
                    this.treeExpandManager.showRecursionDepthSelector(e, expandAllButton);
                }, longPressDelay);
            });
            
            expandAllButton.addEventListener('touchend', () => {
                if (longPressTimer) {
                    clearTimeout(longPressTimer);
                    longPressTimer = null;
                }
            });
            
            expandAllButton.addEventListener('touchmove', () => {
                if (longPressTimer) {
                    clearTimeout(longPressTimer);
                    longPressTimer = null;
                }
            });
            
            // 查找插入位置：在 focus 和 collapse 之间
            const focusButton = toolbar.querySelector('[data-type="focus"]');
            const collapseButton = toolbar.querySelector('[data-type="collapse"]');
            
            if (focusButton && collapseButton) {
                // 在 focus 和 collapse 之间插入
                toolbar.insertBefore(expandAllButton, collapseButton);
                logger.debug("✅ 移动端按钮插入到 focus 和 collapse 之间");
            } else if (focusButton) {
                // 在 focus 按钮后面插入
                toolbar.insertBefore(expandAllButton, focusButton.nextSibling);
                logger.debug("✅ 移动端按钮插入到 focus 按钮后面");
            } else if (collapseButton) {
                // 在折叠按钮前面插入
                toolbar.insertBefore(expandAllButton, collapseButton);
                logger.debug("✅ 移动端按钮插入到折叠按钮前面");
            } else {
                // 备用方案：插入到工具栏末尾
                toolbar.appendChild(expandAllButton);
                logger.debug("✅ 移动端按钮插入到工具栏末尾");
            }
            
            logger.debug("✅ 移动端顶栏按钮'展开所有笔记本'添加成功，使用emoji图标 📖，支持长按修改递归深度");
            
        } catch (error) {
            logger.debug("❌ 添加移动端按钮时出错:", error);
        }
    }

    // 🆕 全局事件委托 - 统一处理桌面端和移动端的折叠按钮点击
    initializeGlobalEventDelegation() {
        if (window.__globalEventDelegationBound) {
            return;
        }

        // 在文档根节点绑定一次，永久有效
        document.addEventListener('click', (e) => {
            // 检查是否是程序化点击，如果是则忽略
            if (e.isProgrammaticClick) {
                return;
            }
            
            // 快速过滤：不在文档树内直接返回
            const treeContainer = e.target.closest('.b3-list.b3-list--background');
            if (!treeContainer) {
                return;
            }
            
            // 检查是否是折叠按钮
            if (Utils.isArrowButton(e.target)) {
                // 检查功能是否启用
                if (!CONFIG.UNFOLD_ALL_SWITCH) {
                    return;
                }
                
                // 防止重复处理
                if (e.target.__isProcessing) {
                    return;
                }
                e.target.__isProcessing = true;
                
                // 创建新的处理器实例并处理事件
                const handler = new TreeHandler();
                handler.handleClickEvent(e);
                
                // 延迟重置处理状态，防止快速重复点击
                setTimeout(() => {
                    e.target.__isProcessing = false;
                }, 100);
            }
        }, true); // 使用捕获阶段，确保能捕获到子元素的点击
        
        window.__globalEventDelegationBound = true;
    }

    // 🆕 注入右键菜单
    injectRightClickMenu() {
        // 检查是否已经注入过
        if (window.__rightClickMenuInjected) {
            logger.debug("✅ 右键菜单已注入，跳过重复注入");
            return;
        }

        try {
            const success = this.injectByMenuCreation();
            
            if (success) {
                window.__rightClickMenuInjected = true;
                logger.debug("✅ 右键菜单注入成功（通过菜单创建监听）");
            } else {
                logger.debug("⚠️ 右键菜单注入失败，将重试");
                // 如果注入失败，延迟重试
                setTimeout(() => {
                    if (!window.__rightClickMenuInjected) {
                        this.injectRightClickMenu();
                    }
                }, 2000);
            }
        } catch (error) {
            logger.debug("❌ 右键菜单注入失败:", error);
            // 注入失败时延迟重试
            setTimeout(() => {
                if (!window.__rightClickMenuInjected) {
                    this.injectRightClickMenu();
                }
            }, 3000);
        }
    }

    // 🆕 使用参考给笔记本添加文档数.js的有效方法注入右键菜单
    injectByMenuCreation() {
        try {
            // 监听右键菜单的创建，参考给笔记本添加文档数.js的方法
            const treeSelector = Utils.isMobile() ? '#sidebar .b3-list--mobile' : '.sy__file';
            
            Utils.whenElementExist(treeSelector).then((fileTree) => {
                const onMenuShow = (event) => {
                    // 获取当前点击的元素
                    let currLi = event.target.closest('li.b3-list-item');
                    
                    // 移动端：使用更严格的过滤，桌面端：允许笔记本右键
                    if (Utils.isMobile()) {
                        // 移动端：只对文件有效，过滤笔记本
                        currLi = event.target.closest('li.b3-list-item:not([data-type="navigation-root"],[data-count="0"])');
                        if (!currLi) return;
                        // 关闭上次的菜单，防止2个菜单冲突
                        document.body.click();
                    } else {
                        // 桌面端：允许笔记本和文件右键
                        if (!currLi) return;
                    }
                    
                    // 等待重命名按钮出现后注入我们的按钮
                    Utils.whenElementExist('button[data-id="rename"]').then(renameBtn => {
                        // 检查是否已经注入过
                        if (renameBtn.parentElement.querySelector('button[data-id="expand-all"]')) {
                            return; // 已经注入过了
                        }
                        
                        // 创建"全部展开"按钮 - 使用SVG图标
                        const html = `<button data-id="expand-all" class="b3-menu__item"><svg class="b3-menu__icon" style=""><use xlink:href="#iconExpand"></use></svg><span class="b3-menu__label">展开子文档</span></button>`;
                        renameBtn.insertAdjacentHTML('afterend', html);
                        
                        // 添加点击事件
                        const expandBtn = renameBtn.parentElement.querySelector('button[data-id="expand-all"]');
                        expandBtn.onclick = async (e) => {
                            e.preventDefault();
                            e.stopPropagation();
                            
                            logger.debug("🎯 右键菜单触发全部展开");
                            
                            // 确定是笔记本还是文件
                            const isNotebook = currLi.getAttribute('data-type') === 'navigation-root';
                            
                            if (isNotebook) {
                                // 笔记本全部展开
                                await this.treeExpandManager.expandNotebookFromRightClick(currLi);
                            } else {
                                // 文件全部展开
                                const notebookId = this.treeExpandManager.getNotebookIdFromElement(currLi);
                                const pathString = currLi.getAttribute('data-path');
                                await this.treeExpandManager.expandFileFromRightClick(currLi, notebookId, pathString);
                            }
                            
                            // 关闭右键菜单
                            document.body.click();
                        };
                        
                        logger.debug("✅ 右键菜单'全部展开'按钮注入成功");
                    });
                };
                
                if (Utils.isMobile()) {
                    // 移动端：监听长按笔记本，800ms后自动展开
                    logger.debug("📱 设置移动端长按监听器...");
                    let longPressTimer = null;
                    const longPressDelay = 800; // 800ms长按延迟
                    
                    fileTree.addEventListener('touchstart', (event) => {
                        const targetLi = event.target.closest('li.b3-list-item');
                        if (!targetLi) return;
                        
                        // 只对笔记本有效
                        if (targetLi.getAttribute('data-type') !== 'navigation-root') return;
                        
                        longPressTimer = setTimeout(async () => {
                            logger.debug("🎯 移动端长按笔记本触发，开始自动展开");
                            
                            // 显示提示
                            this.treeExpandManager.showMobileLongPressTip(targetLi);
                            
                            // 自动展开笔记本
                            await this.treeExpandManager.expandNotebookFromRightClick(targetLi);
                            
                            // 清除定时器
                            longPressTimer = null;
                        }, longPressDelay);
                    });
                    
                    fileTree.addEventListener('touchend', () => {
                        if (longPressTimer) {
                            clearTimeout(longPressTimer);
                            longPressTimer = null;
                        }
                    });
                    
                    fileTree.addEventListener('touchmove', () => {
                        if (longPressTimer) {
                            clearTimeout(longPressTimer);
                            longPressTimer = null;
                        }
                    });
                } else {
                    // 桌面端：监听右键事件和更多按钮点击
                    logger.debug("🖥️ 设置桌面端事件监听器...");
                    fileTree.addEventListener('contextmenu', onMenuShow);
                    // 参考给笔记本添加文档数.js，桌面端也监听更多按钮
                    fileTree.addEventListener('mouseup', (event) => {
                        if (event.target.closest('span[data-type="more-file"]')) {
                            onMenuShow(event);
                        }
                    });
                }
                
                logger.debug("✅ 右键菜单监听器设置成功");
            });
            
            return true;
        } catch (error) {
            logger.debug("❌ 设置右键菜单监听器失败:", error);
            return false;
        }
    }

    // 预加载拼音库
    async preloadPinyinLibrary() {
        try {
            // 在后台预加载拼音库
            setTimeout(async () => {
                const startTime = performance.now(); // 记录开始时间
                
                await this.filterCore.pinyinManager.load();
                
                const endTime = performance.now(); // 记录结束时间
                const duration = endTime - startTime; // 计算耗时
                
                logger.info(`拼音库预加载完成，耗时: ${duration.toFixed(2)}ms`);
            }, 1000); // 延迟1秒加载，避免影响初始化速度
        } catch (error) {
            logger.warn('拼音库预加载失败:', error);
        }
    }

    // 注册清理函数
    registerCleanup() {
        const cleanup = () => {
            this.removeAllFilters();
            this.observerManager.stopAllObservers();
            this.filterCore.cleanup();
            
            // 🆕 清理展开文档树功能
            if (CONFIG.EXPAND_TREE_ENABLED && this.treeExpandManager) {
                this.cleanupTreeExpandFeatures();
            }
            
            // 清理按钮
            Utils.safeQuerySelectorAll('.dock__item[aria-label*="筛选过滤器"]').forEach(btn => btn.remove());
            
            // 清理样式
            const style = document.getElementById('filter-highlight-style');
            if (style) style.remove();
        };

        const currentScript = document.currentScript?.src;
        if (currentScript) {
            const currentFilename = currentScript.split('/').pop();
            if (window.__registerCleanupHandler) {
                window.__registerCleanupHandler(currentFilename, cleanup);
            }
        }
    }

    // 🆕 清理展开文档树功能
    cleanupTreeExpandFeatures() {
        try {
            logger.debug('🧹 开始清理展开文档树功能...');
            
            // 清理全局事件委托
            if (window.__globalEventDelegationBound) {
                window.__globalEventDelegationBound = false;
                logger.debug('✅ 清理全局事件委托标记');
            }
            
            // 清理右键菜单注入标记
            if (window.__rightClickMenuInjected) {
                window.__rightClickMenuInjected = false;
                logger.debug('✅ 清理右键菜单注入标记');
            }
            
            // 清理展开按钮
            Utils.safeQuerySelectorAll('[data-type="expand-all-notebooks"]').forEach(btn => {
                btn.remove();
            });
            
            // 清理右键菜单中的展开按钮
            Utils.safeQuerySelectorAll('button[data-id="expand-all"]').forEach(btn => {
                btn.remove();
            });
            
            // 清理递归深度选择器
            Utils.safeQuerySelectorAll('.recursion-depth-selector').forEach(selector => {
                selector.remove();
            });
            
            // 清理移动端长按提示
            Utils.safeQuerySelectorAll('.mobile-longpress-tip').forEach(tip => {
                tip.remove();
            });
            
            // 清理树展开管理器
            if (this.treeExpandManager) {
                this.treeExpandManager.cleanup();
            }
            
            logger.debug('✅ 展开文档树功能清理完成');
        } catch (error) {
            logger.debug('❌ 清理展开文档树功能时出错:', error);
        }
    }
}

// ================= 🆕 展开文档树核心类 =================

// 🆕 树节点处理类 - 优化版本
class TreeHandler {
    constructor() {
        this.isProcessing = false;
        this.startTime = 0;
    }

    // 递归展开所有子孙节点 - 优化版本
    async expandAllDescendants(arrowSpan, currentDepth = 0) {
        const levelStartTime = Date.now();
        
        // 🆕 检查递归深度限制
        if (CONFIG.MAX_RECURSION_DEPTH === 0) {
            if (CONFIG.SHOW_DEPTH_INFO) {
                logger.debug(`🛑 递归深度设置为0，不进行递归展开`);
            }
            return;
        }
        
        if (CONFIG.MAX_RECURSION_DEPTH !== 99 && currentDepth >= CONFIG.MAX_RECURSION_DEPTH) {
            if (CONFIG.SHOW_DEPTH_INFO) {
                logger.debug(`🛑 达到最大递归深度 ${CONFIG.MAX_RECURSION_DEPTH}，停止展开`);
            }
            return;
        }
        
        if (CONFIG.SHOW_DEPTH_INFO) {
            logger.debug(`🔄 递归展开第 ${currentDepth + 1} 层，最大深度: ${CONFIG.MAX_RECURSION_DEPTH}`);
        }

        const parentLi = Utils.getParentLi(arrowSpan);
        if (!parentLi) return;

        const childList = Utils.findChildList(parentLi);
        if (!childList) return;

        const childNodes = Array.from(childList.children);
        if (CONFIG.SHOW_DEPTH_INFO) {
            logger.debug(`📋 找到子节点数量: ${childNodes.length}`);
        }

        let expandedCount = 0;

        // 批量处理子节点，每个节点使用自己的等待时间
        const promises = childNodes.map(async (childNode) => {
            const childToggle = childNode.querySelector('span.b3-list-item__toggle:not(.fn__hidden)');

            if (childToggle && Utils.hasChildren(childToggle)) {
                if (!Utils.isExpanded(childToggle)) {
                    const childStartTime = Date.now();
                    if (CONFIG.SHOW_DEPTH_INFO) {
                        logger.debug(`🔄 展开第 ${currentDepth + 1} 层子节点`);
                    }

                    // 🆕 修复：使用 dispatchEvent 而不是 click() 来避免触发全局事件监听器
                    const clickEvent = new MouseEvent('click', {
                        bubbles: true,
                        cancelable: true,
                        view: window
                    });
                    clickEvent.isProgrammaticClick = true; // 标记为程序化点击
                    childToggle.dispatchEvent(clickEvent);
                    
                    // 使用配置的统一等待时间
                    const sleepTime = CONFIG.NODE_WAIT_TIME;
                    await Utils.sleep(sleepTime);

                    expandedCount++;
                }

                // 递归展开这个子节点的子孙节点，深度+1
                await this.expandAllDescendants(childToggle, currentDepth + 1);
            }
        });

        // 等待所有子节点处理完成
        await Promise.all(promises);

        const levelTime = Date.now() - levelStartTime;
        if (CONFIG.SHOW_DEPTH_INFO) {
            logger.debug(`✅ 完成第 ${currentDepth + 1} 层递归展开，本层级耗时：${levelTime}ms，展开子节点：${expandedCount}个`);
        } else {
            logger.debug(`✅ 完成递归展开，本层级耗时：${levelTime}ms，展开子节点：${expandedCount}个`);
        }
    }

    // 🆕 展开整个容器中所有未展开的折叠按钮
    async expandAllUnfoldedNodes(container) {
        let totalExpanded = 0;
        
        // 查找容器中所有未展开的折叠按钮
        const allToggles = container.querySelectorAll('span.b3-list-item__toggle:not(.fn__hidden)');
        
        for (const toggle of allToggles) {
            if (Utils.hasChildren(toggle) && !Utils.isExpanded(toggle)) {
                // 使用 dispatchEvent 而不是 click() 来避免触发全局事件监听器
                const clickEvent = new MouseEvent('click', {
                    bubbles: true,
                    cancelable: true,
                    view: window
                });
                clickEvent.isProgrammaticClick = true; // 标记为程序化点击
                toggle.dispatchEvent(clickEvent);
                
                // 等待展开完成
                await Utils.sleep(CONFIG.NODE_WAIT_TIME);
                
                // 递归展开这个节点的子孙节点（从第0层开始计算深度）
                await this.expandAllDescendants(toggle, 0);
                
                totalExpanded++;
            }
        }
        
        return totalExpanded;
    }

    // 处理鼠标点击事件 - 优化版本
    async handleClickEvent(event) {
        const element = event.target;

        // 快速过滤：不是折叠按钮的直接返回
        if (!Utils.isArrowButton(element)) {
            return;
        }

        // 检查功能是否启用
        if (!CONFIG.UNFOLD_ALL_SWITCH) {
            return;
        }

        // 防止重复处理
        if (this.isProcessing) {
            logger.debug("❌ 正在处理中，忽略重复点击");
            return;
        }

        // 检查是否有子节点
        if (!Utils.hasChildren(element)) {
            return;
        }

        // 记录开始时间
        this.startTime = Date.now();
        logger.debug("⏱️ 开始一键展开所有子孙节点");

        this.isProcessing = true;

        try {
            // 使用配置的统一等待时间
            const initialSleepTime = CONFIG.NODE_WAIT_TIME;
            
            // 智能等待思源完成展开，带重试机制
            const expansionSuccess = await this.waitForExpansion(element, initialSleepTime);
            
            if (expansionSuccess) {
                logger.debug("✅ 开始递归展开所有子孙节点");
                await this.expandAllDescendants(element);

                const totalTime = Date.now() - this.startTime;
                logger.success(`⏱️ 展开完成！总耗时：${totalTime}ms`);
            } else {
                logger.debug("❌ 思源展开失败，无法继续递归展开");
            }
        } catch (error) {
            logger.debug("❌ 展开子孙节点时出错:", error);
        } finally {
            this.isProcessing = false;
        }
    }

    // 智能等待思源完成展开
    async waitForExpansion(element, baseWaitTime) {
        const maxRetries = CONFIG.EXPANSION_RETRY.MAX_RETRIES;
        let retryCount = 0;
        let totalWaitTime = 0;
        
        while (retryCount < maxRetries) {
            // 等待基础时间
            await Utils.sleep(baseWaitTime);
            totalWaitTime += baseWaitTime;
            
            // 检查是否已经展开
            if (Utils.isExpanded(element)) {
                if (CONFIG.SHOW_DEPTH_INFO) {
                    logger.debug(`✅ 思源展开成功！总等待时间: ${totalWaitTime}ms，重试次数: ${retryCount}`);
                }
                return true;
            }
            
            retryCount++;
            
            if (retryCount < maxRetries) {
                // 计算递增等待时间
                const incrementalWait = baseWaitTime * (1 + retryCount * CONFIG.EXPANSION_RETRY.INCREMENTAL_FACTOR);
                await Utils.sleep(incrementalWait);
                totalWaitTime += incrementalWait;
            }
        }
        
        if (CONFIG.SHOW_DEPTH_INFO) {
            logger.debug(`❌ 思源展开失败，已重试 ${maxRetries} 次，总等待时间: ${totalWaitTime}ms`);
        }
        return false;
    }

    // 清理资源
    destroy() {
        this.isProcessing = false;
        this.startTime = 0;
    }
}

// 🆕 文件树刷新管理器
class FileTreeRefreshManager {
    /**
     * 刷新文件树
     * @param {Object} options 刷新选项
     * @param {string} options.notebook 需要刷新的笔记本ID，为空则刷新所有笔记本
     * @param {boolean} options.force 是否强制刷新，忽略缓存
     * @param {string} options.path 需要刷新的路径，为空则刷新整个笔记本
     * @returns {Promise<boolean>} 是否刷新成功
     */
    static async refreshFileTree(options = {}) {
        const { notebook = '', force = CONFIG.REFRESH_FILETREE.FORCE_REFRESH, path = '' } = options;
        
        if (!CONFIG.REFRESH_FILETREE.ENABLED) {
            logger.debug('🔄 文件树刷新功能已禁用，跳过刷新');
            return false;
        }

        try {
            const token = localStorage.getItem('authToken') || '';
                
            logger.debug('🔄 开始刷新文件树...');
            
            const response = await fetch('/api/filetree/refreshFiletree', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Token ${token}`
                },
                body: JSON.stringify({
                    notebook: notebook,
                    force: force,
                    path: path
                })
            });

            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }

            const result = await response.json();
            
            if (result && result.code === 0) {
                logger.debug('✅ 文件树刷新成功');
                return true;
            } else {
                logger.debug(`❌ 文件树刷新失败，错误: ${result?.msg || '未知错误'}`);
                return false;
            }
        } catch (error) {
            logger.debug('❌ 文件树刷新失败:', error);
            return false;
        }
    }

    /**
     * 刷新所有笔记本的文件树
     * @returns {Promise<boolean>} 是否刷新成功
     */
    static async refreshAllNotebooks() {
        return await this.refreshFileTree({
            notebook: '',  // 空字符串表示刷新所有笔记本
            force: CONFIG.REFRESH_FILETREE.FORCE_REFRESH,
            path: ''       // 空字符串表示刷新整个笔记本
        });
    }
}

// 🆕 展开文档树管理器
class TreeExpandManager {
    constructor() {
        this.isExpandingAllNotebooks = false;
        this.resetClickCount = 0;
    }

    // 🆕 获取当前递归深度的标签文本
    getCurrentDepthLabel() {
        const depth = CONFIG.MAX_RECURSION_DEPTH;
        if (depth === 0) {
            return '展开所有笔记本\n仅展开当前，右击可修改';
        } else if (depth === 99) {
            return '展开所有笔记本\n全部展开，右击可修改';
        } else {
            const actualLayers = depth + 1; // 递归层级+1
            return `展开所有笔记本\n每次展开${actualLayers}层，右击可修改`;
        }
    }

    // 🆕 更新所有按钮的aria-label
    updateAllButtonLabels() {
        const newLabel = this.getCurrentDepthLabel();
        
        // 更新桌面端按钮
        const desktopButton = document.querySelector('.sy__file [data-type="expand-all-notebooks"]');
        if (desktopButton) {
            desktopButton.setAttribute('aria-label', newLabel);
        }
        
        // 更新移动端按钮
        const mobileButton = document.querySelector('[data-type="sidebar-file"] [data-type="expand-all-notebooks"]');
        if (mobileButton) {
            mobileButton.setAttribute('aria-label', newLabel);
        }
        
        logger.debug(`🔄 按钮标签已更新: ${newLabel}`);
    }

    // 🆕 显示递归深度选择器
    showRecursionDepthSelector(event, buttonElement) {
        // 移除已存在的选择器
        const existingSelector = document.querySelector('.recursion-depth-selector');
        if (existingSelector) {
            existingSelector.remove();
        }
        
        // 创建选择器容器
        const selector = document.createElement('div');
        selector.className = 'recursion-depth-selector';
        selector.style.cssText = `
            position: fixed !important;
            z-index: 9999 !important;
            background: var(--b3-theme-background) !important;
            border: 1px solid var(--b3-theme-border) !important;
            border-radius: 8px !important;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
            padding: 10px !important;
            min-width: 120px !important;
            max-width: 140px !important;
            font-family: var(--b3-theme-font-family) !important;
            font-size: 14px !important;
            color: var(--b3-theme-on-surface) !important;
            /* 🎯 关键：强制位置，防止任何CSS干扰 */
            left: 0 !important;
            top: 0 !important;
            transform: none !important;
            margin: 0 !important;
        `;
        
        // 创建标题
        const title = document.createElement('div');
        title.textContent = '选择展开层级';
        title.style.cssText = `
            font-weight: bold;
            margin-bottom: 4px;
            padding-bottom: 6px;
            border-bottom: 1px solid var(--b3-theme-border);
            color: var(--b3-theme-on-surface);
            text-align: center;
            display: flex;
            justify-content: center;
            align-items: center;
        `;
        selector.appendChild(title);
        
        // 创建选项列表
        const options = [
            { value: 0, label: '1层 (原生展开)' },   // 0表示不递归展开，只展开当前节点
            { value: 1, label: '2层 (小步展开)' },
            { value: 2, label: '3层 (平衡展开)' },
            { value: 3, label: '4层 (深度展开)' },
            { value: 99, label: '不限 (完全展开)' }  // 99表示不限递归深度
        ];
        
        options.forEach(option => {
            const optionDiv = document.createElement('div');
            optionDiv.setAttribute('data-value', option.value);
            optionDiv.style.cssText = `
                padding: 4px 8px;
                margin: 1px 0;
                border-radius: 4px;
                cursor: pointer;
                transition: background-color 0.2s;
                display: flex;
                align-items: center;
                min-height: 18px;
                line-height: 1;
            `;
            
            // 高亮当前选中的值
            if (option.value === CONFIG.MAX_RECURSION_DEPTH || 
                (option.value === 99 && CONFIG.MAX_RECURSION_DEPTH === 99)) {
                optionDiv.style.background = 'var(--b3-theme-primary)';
                optionDiv.style.color = 'var(--b3-theme-on-primary)';
            }
            
            // 创建标签
            const label = document.createElement('div');
            label.textContent = option.label;
            label.style.cssText = `
                cursor: pointer;
                flex: 1;
                word-wrap: break-word;
                white-space: normal;
                line-height: 1.2;
                margin: 0;
                padding: 0;
                display: flex;
                align-items: center;
                min-height: 16px;
                vertical-align: middle;
                justify-content: center;
            `;
            
            optionDiv.appendChild(label);
            
            // 添加悬停效果
            optionDiv.addEventListener('mouseenter', () => {
                if (option.value !== CONFIG.MAX_RECURSION_DEPTH) {
                    optionDiv.style.background = 'var(--b3-theme-surface)';
                }
            });
            
            optionDiv.addEventListener('mouseleave', () => {
                if (option.value !== CONFIG.MAX_RECURSION_DEPTH) {
                    optionDiv.style.background = 'transparent';
                }
            });
            
            // 添加点击事件
            optionDiv.addEventListener('click', async () => {
                // 更新选中状态
                options.forEach(opt => {
                    const optDiv = selector.querySelector(`[data-value="${opt.value}"]`);
                    if (optDiv) {
                        optDiv.style.background = 'transparent';
                        optDiv.style.color = 'var(--b3-theme-on-surface)';
                    }
                });
                
                optionDiv.style.background = 'var(--b3-theme-primary)';
                optionDiv.style.color = 'var(--b3-theme-on-primary)';
                
                // 更新配置
                const newDepth = parseInt(option.value);
                CONFIG.MAX_RECURSION_DEPTH = newDepth;
                
                // 🆕 保存到本地存储
                try {
                    await StorageManager.setItem(CONFIG.STORAGE.TREE_EXPAND.MAX_RECURSION_DEPTH, newDepth, CONFIG.STORAGE.APP_ID);
                    logger.debug(`💾 递归深度配置已保存到本地存储: ${newDepth}`);
                } catch (error) {
                    logger.debug('❌ 保存递归深度配置失败:', error);
                }
                
                // 🆕 更新所有按钮的aria-label
                this.updateAllButtonLabels();
                
                // 显示确认信息
                let confirmMsg;
                if (newDepth === 0) {
                    confirmMsg = '已设置为：仅展开当前节点，不进行递归展开';
                } else if (newDepth === 99) {
                    confirmMsg = '已设置为：不限递归深度';
                } else {
                    confirmMsg = `已设置为：${newDepth}层递归深度`;
                }
                logger.info(`✅ ${confirmMsg}`);
                
                // 延迟关闭选择器
                setTimeout(() => {
                    selector.remove();
                }, 800);
            });
            
            selector.appendChild(optionDiv);
        });
        
        // 添加说明文字
        const description = document.createElement('div');
        description.innerHTML = '提示：每次点击展开的层数，<br>展开较快可能导致文字重叠，<br>选择完全展开后会刷新索引。';
        description.style.cssText = `
            font-size: 10px;
            color: var(--b3-theme-on-surface-variant);
            margin-top: 5px;
            padding-top: 6px;
            border-top: 1px solid var(--b3-theme-border);
            line-height: 1.4;
            word-wrap: break-word;
            white-space: normal;
            text-align: center;
        `;
        selector.appendChild(description);
        
        // 计算位置（在按钮附近显示）
        const buttonRect = buttonElement.getBoundingClientRect();
        const selectorWidth = 140; // 使用max-width作为预估宽度
        const selectorHeight = 250; // 调整预估高度，更接近实际值
        
        // 初始位置计算
        let left = buttonRect.left;
        let top = buttonRect.bottom + 8;
        

        
        // 边界检查
        
        // 检查右边界
        if (left + selectorWidth > window.innerWidth) {
            left = window.innerWidth - selectorWidth - 8;
        }
        
        // 检查下边界
        if (top + selectorHeight > window.innerHeight) {
            top = buttonRect.top - selectorHeight - 8;
        }
        
        // 检查左边界
        if (left < 8) {
            left = 8;
        }
        
        // 检查上边界
        if (top < 8) {
            top = 8;
        }
        

        
        // 🎯 关键：使用!important强制设置位置
        selector.style.setProperty('left', left + 'px', 'important');
        selector.style.setProperty('top', top + 'px', 'important');
        
        // 添加到页面
        document.body.appendChild(selector);
    }

    // 🆕 处理"展开所有笔记本"按钮点击
    async handleExpandAllNotebooks() {
        // 🆕 防止重复点击
        if (this.isExpandingAllNotebooks) {
           logger.debug("❌ 正在展开所有笔记本，请等待当前操作完成...");
            return;
        }
        
        this.isExpandingAllNotebooks = true;
        

        
       logger.debug("🚀 开始智能展开所有笔记本...");

        try {
            let treeContainers, allContainers;
            
            if (Utils.isMobile()){
                // 移动端：使用移动端选择器
               logger.debug("🔍 移动端：查找文档树容器...");
                const mobilePanel = await Utils.whenElementExist('[data-type="sidebar-file"]');
                if (!mobilePanel) {
                   logger.debug("❌ 移动端文档树面板未找到");
                    return;
                }
                
                allContainers = mobilePanel.querySelectorAll('.b3-list.b3-list--background');
                if (allContainers.length === 0) {
                   logger.debug("❌ 移动端未找到任何文档树容器");
                    return;
                }
                
               logger.debug(`🔍 移动端找到 ${allContainers.length} 个文档树容器`);
            } else {
                // 桌面端：使用桌面端选择器
               logger.debug("🔍 桌面端：查找根笔记本容器...");
                await Utils.whenElementExist('.sy__file .b3-list.b3-list--background');
                allContainers = document.querySelectorAll('.sy__file .b3-list.b3-list--background');
                
                if (allContainers.length === 0) {
                   logger.debug("❌ 桌面端未找到任何根笔记本容器");
                    return;
                }
                
               logger.debug(`🔍 桌面端找到 ${allContainers.length} 个根笔记本容器`);
            }

           logger.debug(`🔍 找到 ${allContainers.length} 个根笔记本，开始智能展开...`);

            const startTime = Date.now();
            let totalExpanded = 0;

            // 🆕 根据配置选择展开方式
            if (CONFIG.EXPAND_ALL_NOTEBOOKS.PARALLEL_EXPANSION) {
                // 并行展开：为每个根笔记本容器创建展开任务
               logger.debug("⚡ 使用并行展开模式...");
                const expandTasks = Array.from(allContainers).map(async (container, index) => {
                    return await this.expandSingleNotebook(container, index);
                });

                // 等待所有展开任务完成
                const results = await Promise.all(expandTasks);
                totalExpanded = results.reduce((sum, count) => sum + count, 0);
            } else {
                // 逐个展开：避免重叠和混乱
               logger.debug("🔄 使用逐个展开模式，避免重叠...");
                for (let i = 0; i < allContainers.length; i++) {
                    const count = await this.expandSingleNotebook(allContainers[i], i);
                    totalExpanded += count;
                }
            }

            const totalTime = Date.now() - startTime;
           logger.success(`🎉 所有笔记本智能展开完成！总耗时：${totalTime}ms，成功展开：${totalExpanded}个`);
            
            // 🆕 展开完成后刷新文件树
            if (CONFIG.REFRESH_FILETREE.AFTER_EXPAND_ALL && CONFIG.MAX_RECURSION_DEPTH === 99) {
               logger.debug('🔄 展开完成，检测到完全展开模式(层级99)，开始刷新文件树...');
                
                try {
                    const refreshSuccess = await FileTreeRefreshManager.refreshAllNotebooks();
                    if (refreshSuccess) {
                       logger.debug('✅ 文件树刷新完成，文档树已更新');
                    } else {
                       logger.debug('⚠️ 文件树刷新失败，但展开操作已完成');
                       logger.debug('💡 提示：可以尝试手动刷新页面，或者等待思源笔记完全加载');
                    }
                } catch (error) {
                   logger.debug('❌ 文件树刷新过程中出错:', error);
                }
            } else if (CONFIG.REFRESH_FILETREE.AFTER_EXPAND_ALL && CONFIG.MAX_RECURSION_DEPTH !== 99) {
               logger.debug(`🔄 展开完成，当前展开层级为${CONFIG.MAX_RECURSION_DEPTH}，非完全展开模式，跳过文件树刷新`);
            }
        } catch (error) {
           logger.debug("❌ 展开所有笔记本失败:", error);
        } finally {
            // 🆕 重置全局处理状态
            this.isExpandingAllNotebooks = false;
        }
    }

    // 🆕 展开单个笔记本的辅助函数
    async expandSingleNotebook(container, index) {
        // 查找根笔记本的折叠按钮
        const rootToggle = container.querySelector('li[data-path="/"] span.b3-list-item__toggle:not(.fn__hidden)');
        if (!rootToggle) {
            return 0; // 简化：移除警告日志
        }

        // 🆕 智能展开逻辑：检查根笔记本状态
        if (!Utils.isExpanded(rootToggle)) {
            // 根笔记本未展开：按原有逻辑展开
           logger.debug(`🔄 展开第 ${index + 1} 个根笔记本...`);
            
            // 使用 dispatchEvent 而不是 click() 来避免触发全局事件监听器
            const clickEvent = new MouseEvent('click', {
                bubbles: true,
                cancelable: true,
                view: window
            });
            clickEvent.isProgrammaticClick = true; // 标记为程序化点击
            rootToggle.dispatchEvent(clickEvent);

            // 使用统一等待时间
            await Utils.sleep(CONFIG.NODE_WAIT_TIME);

            // 递归展开所有子孙节点
            const handler = new TreeHandler();
            await handler.expandAllDescendants(rootToggle);
            
            return 1; // 返回展开的笔记本数量
        } else {
            // 🆕 根笔记本已展开：查找整个面板中所有未展开的折叠按钮
           logger.debug(`🔍 第 ${index + 1} 个根笔记本已展开，查找未展开的子节点...`);
            
            const handler = new TreeHandler();
            const expandedCount = await handler.expandAllUnfoldedNodes(container);
            
            if (expandedCount > 0) {
               logger.debug(`✅ 第 ${index + 1} 个根笔记本展开完成，新增展开 ${expandedCount} 个节点`);
            } else {
               logger.debug(`✅ 第 ${index + 1} 个根笔记本已完全展开`);
            }
            
            return expandedCount; // 返回展开的节点数量
        }
    }

    // 🆕 从元素获取笔记本ID
    getNotebookIdFromElement(element) {
        if (!element) return null;
        
        // 向上查找包含笔记本信息的父元素
        const ulElement = element.closest('ul[data-url]');
        if (ulElement) {
            return ulElement.getAttribute('data-url');
        }
        
        return null;
    }

    // 🆕 从右键菜单展开笔记本
    async expandNotebookFromRightClick(liElement) {
        try {
            // 获取笔记本ID
            const notebookId = liElement.parentElement.getAttribute('data-url');
            if (!notebookId) {
               logger.debug("❌ 未找到笔记本ID");
                return;
            }

           logger.debug(`🔄 开始展开笔记本: ${notebookId}`);

            // 查找笔记本的折叠按钮
            const toggleButton = liElement.querySelector('span.b3-list-item__toggle:not(.fn__hidden)');
            if (!toggleButton) {
               logger.debug("❌ 未找到笔记本折叠按钮");
                return;
            }

            // 如果笔记本未展开，先展开
            if (!Utils.isExpanded(toggleButton)) {
                const clickEvent = new MouseEvent('click', {
                    bubbles: true,
                    cancelable: true,
                    view: window
                });
                clickEvent.isProgrammaticClick = true;
                toggleButton.dispatchEvent(clickEvent);
                
                // 等待展开完成
                await Utils.sleep(CONFIG.NODE_WAIT_TIME);
            }

            // 递归展开所有子孙节点
            const handler = new TreeHandler();
            await handler.expandAllDescendants(toggleButton);
            
           logger.debug(`✅ 笔记本 ${notebookId} 全部展开完成`);
        } catch (error) {
           logger.debug("❌ 展开笔记本失败:", error);
        }
    }

    // 🆕 从右键菜单展开文件
    async expandFileFromRightClick(liElement, notebookId, pathString) {
        try {
            // 获取文件ID
            const fileId = liElement.getAttribute('data-node-id');
            if (!fileId) {
               logger.debug("❌ 未找到文件ID");
                return;
            }

           logger.debug(`🔄 开始展开文件: ${fileId}`);

            // 查找文件的折叠按钮
            const toggleButton = liElement.querySelector('span.b3-list-item__toggle:not(.fn__hidden)');
            if (!toggleButton) {
               logger.debug("❌ 未找到文件折叠按钮");
                return;
            }

            // 如果文件未展开，先展开
            if (!Utils.isExpanded(toggleButton)) {
                const clickEvent = new MouseEvent('click', {
                    bubbles: true,
                    cancelable: true,
                    view: window
                });
                clickEvent.isProgrammaticClick = true;
                toggleButton.dispatchEvent(clickEvent);
                
                // 等待展开完成
                await Utils.sleep(CONFIG.NODE_WAIT_TIME);
            }

            // 递归展开所有子孙节点
            const handler = new TreeHandler();
            await handler.expandAllDescendants(toggleButton);
            
           logger.debug(`✅ 文件 ${fileId} 全部展开完成`);
        } catch (error) {
           logger.debug("❌ 展开文件失败:", error);
        }
    }

    // 🆕 移动端长按提示函数
    showMobileLongPressTip(targetLi) {
        try {
            // 移除已存在的提示
            const existingTip = document.querySelector('.mobile-longpress-tip');
            if (existingTip) {
                existingTip.remove();
            }
            
            // 创建提示元素
            const tip = document.createElement('div');
            tip.className = 'mobile-longpress-tip';
            tip.innerHTML = '📖 正在展开笔记本...';
            
            // 添加到页面
            document.body.appendChild(tip);
            
            // 3秒后自动移除提示
            setTimeout(() => {
                if (tip.parentNode) {
                    tip.remove();
                }
            }, 3000);
            
           logger.debug("✅ 移动端长按提示显示成功");
        } catch (error) {
           logger.debug("❌ 显示移动端长按提示失败:", error);
        }
    }
}

// ================= 启动应用 =================
const app = new FilterApp();
app.init();

// 应用启动完成
})(); 